
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.
*/
// Symbol factory
import { each, isArray, retrieve2 } from 'tvrender/lib/core/util.js';
import * as graphic from './graphic.js';
import BoundingRect from 'tvrender/lib/core/BoundingRect.js';
import { calculateTextPosition } from 'tvrender/lib/contain/text.js';
import { parsePercent } from './number.js';
/**
 * Triangle shape
 * @inner
 */
var Triangle = graphic.Path.extend({
  type: 'triangle',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0
  },
  buildPath: function (path, shape) {
    var cx = shape.cx;
    var cy = shape.cy;
    var width = shape.width / 2;
    var height = shape.height / 2;
    path.moveTo(cx, cy - height);
    path.lineTo(cx + width, cy + height);
    path.lineTo(cx - width, cy + height);
    path.closePath();
  }
});
/**
 * Diamond shape
 * @inner
 */
var Diamond = graphic.Path.extend({
  type: 'diamond',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0
  },
  buildPath: function (path, shape) {
    var cx = shape.cx;
    var cy = shape.cy;
    var width = shape.width / 2;
    var height = shape.height / 2;
    path.moveTo(cx, cy - height);
    path.lineTo(cx + width, cy);
    path.lineTo(cx, cy + height);
    path.lineTo(cx - width, cy);
    path.closePath();
  }
});
/**
 * Pin shape
 * @inner
 */
var Pin = graphic.Path.extend({
  type: 'pin',
  shape: {
    // x, y on the cusp
    x: 0,
    y: 0,
    width: 0,
    height: 0
  },
  buildPath: function (path, shape) {
    var x = shape.x;
    var y = shape.y;
    var w = shape.width / 5 * 3;
    // Height must be larger than width
    var h = Math.max(w, shape.height);
    var r = w / 2;
    // Dist on y with tangent point and circle center
    var dy = r * r / (h - r);
    var cy = y - h + r + dy;
    var angle = Math.asin(dy / r);
    // Dist on x with tangent point and circle center
    var dx = Math.cos(angle) * r;
    var tanX = Math.sin(angle);
    var tanY = Math.cos(angle);
    var cpLen = r * 0.6;
    var cpLen2 = r * 0.7;
    path.moveTo(x - dx, cy + dy);
    path.arc(x, cy, r, Math.PI - angle, Math.PI * 2 + angle);
    path.bezierCurveTo(x + dx - tanX * cpLen, cy + dy + tanY * cpLen, x, y - cpLen2, x, y);
    path.bezierCurveTo(x, y - cpLen2, x - dx + tanX * cpLen, cy + dy + tanY * cpLen, x - dx, cy + dy);
    path.closePath();
  }
});
/**
 * Arrow shape
 * @inner
 */
var Arrow = graphic.Path.extend({
  type: 'arrow',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0
  },
  buildPath: function (ctx, shape) {
    var height = shape.height;
    var width = shape.width;
    var x = shape.x;
    var y = shape.y;
    var dx = width / 3 * 2;
    ctx.moveTo(x, y);
    ctx.lineTo(x + dx, y + height);
    ctx.lineTo(x, y + height / 4 * 3);
    ctx.lineTo(x - dx, y + height);
    ctx.lineTo(x, y);
    ctx.closePath();
  }
});
var Cross = graphic.Path.extend({
  type: 'cross',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0
  },
  buildPath: function (ctx, shape) {
    var height = shape.height;
    var width = shape.width;
    var x = shape.x;
    var y = shape.y;
    var dx = width / 3;
    var dy = height / 3;
    ctx.moveTo(x - dx * 0.5, y + dy * 1.5);
    ctx.lineTo(x + dx * 0.5, y + dy * 1.5);
    ctx.lineTo(x + dx * 0.5, y + dy * 0.5);
    ctx.lineTo(x + dx * 1.5, y + dy * 0.5);
    ctx.lineTo(x + dx * 1.5, y - dy * 0.5);
    ctx.lineTo(x + dx * 0.5, y - dy * 0.5);
    ctx.lineTo(x + dx * 0.5, y - dy * 1.5);
    ctx.lineTo(x - dx * 0.5, y - dy * 1.5);
    ctx.lineTo(x - dx * 0.5, y - dy * 0.5);
    ctx.lineTo(x - dx * 1.5, y - dy * 0.5);
    ctx.lineTo(x - dx * 1.5, y + dy * 0.5);
    ctx.lineTo(x - dx * 0.5, y + dy * 0.5);
    ctx.lineTo(x - dx * 0.5, y + dy * 1.5);
    ctx.closePath();
  }
});
var LabelDown = graphic.Path.extend({
  type: 'labelDown',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    r: 0,
    triangleWidth: 0
  },
  buildPath: function (ctx, shape) {
    var x = shape.x,
      y = shape.y,
      width = shape.width,
      height = shape.height,
      r = shape.r,
      triangleWidth = shape.triangleWidth;
    var triangleHeight = triangleWidth;
    // const triangleWidth = 6;
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + width - r, y);
    ctx.arc(x + width - r, y + r, r, -Math.PI / 2, 0);
    ctx.lineTo(x + width, y + height - r);
    ctx.arc(x + width - r, y + height - r, r, 0, Math.PI / 2);
    ctx.lineTo(x + width / 2 + triangleWidth, y + height);
    ctx.lineTo(x + width / 2, y + height + triangleHeight);
    ctx.lineTo(x + width / 2 - triangleWidth, y + height);
    ctx.lineTo(x + r, y + height);
    ctx.arc(x + r, y + height - r, r, Math.PI / 2, Math.PI);
    ctx.lineTo(x, y + r);
    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
  }
});
var LabelUp = graphic.Path.extend({
  type: 'labelUp',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    r: 0,
    triangleWidth: 0
  },
  buildPath: function (ctx, shape) {
    var x = shape.x,
      y = shape.y,
      width = shape.width,
      height = shape.height,
      r = shape.r,
      triangleWidth = shape.triangleWidth;
    var triangleHeight = triangleWidth;
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + width / 2 - triangleWidth, y);
    ctx.lineTo(x + width / 2, y - triangleHeight);
    ctx.lineTo(x + width / 2 + triangleWidth, y);
    ctx.lineTo(x + width - r, y);
    ctx.arc(x + width - r, y + r, r, -Math.PI / 2, 0);
    ctx.lineTo(x + width, y + height - r);
    ctx.arc(x + width - r, y + height - r, r, 0, Math.PI / 2);
    ctx.lineTo(x + r, y + height);
    ctx.arc(x + r, y + height - r, r, Math.PI / 2, Math.PI);
    ctx.lineTo(x, y + r);
    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
  }
});
var LabelLeft = graphic.Path.extend({
  type: 'labelLeft',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    r: 0,
    triangleWidth: 0
  },
  buildPath: function (ctx, shape) {
    var x = shape.x,
      y = shape.y,
      width = shape.width,
      height = shape.height,
      r = shape.r,
      triangleWidth = shape.triangleWidth;
    var triangleHeight = triangleWidth;
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + width - r, y);
    ctx.arc(x + width - r, y + r, r, -Math.PI / 2, 0);
    ctx.lineTo(x + width, y + height - r);
    ctx.arc(x + width - r, y + height - r, r, 0, Math.PI / 2);
    ctx.lineTo(x + r, y + height);
    ctx.arc(x + r, y + height - r, r, Math.PI / 2, Math.PI);
    ctx.lineTo(x, y + height / 2 + triangleWidth);
    ctx.lineTo(x - triangleHeight, y + height / 2);
    ctx.lineTo(x, y + height / 2 - triangleWidth);
    ctx.lineTo(x, y + r);
    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
  }
});
var LabelRight = graphic.Path.extend({
  type: 'labelRight',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    r: 0,
    triangleWidth: 0
  },
  buildPath: function (ctx, shape) {
    var x = shape.x,
      y = shape.y,
      width = shape.width,
      height = shape.height,
      r = shape.r,
      triangleWidth = shape.triangleWidth;
    var triangleHeight = triangleWidth;
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + width - r, y);
    ctx.arc(x + width - r, y + r, r, -Math.PI / 2, 0);
    ctx.lineTo(x + width, y + height / 2 - triangleWidth);
    ctx.lineTo(x + width + triangleHeight, y + height / 2);
    ctx.lineTo(x + width, y + height / 2 + triangleWidth);
    ctx.lineTo(x + width, y + height - r);
    ctx.arc(x + width - r, y + height - r, r, 0, Math.PI / 2);
    ctx.lineTo(x + r, y + height);
    ctx.arc(x + r, y + height - r, r, Math.PI / 2, Math.PI);
    ctx.lineTo(x, y + r);
    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
  }
});
var LabelLowerLeft = graphic.Path.extend({
  type: 'labelLowerLeft',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    r: 0,
    offsetY: 0,
    offsetX: 0,
    offsetWidth: 0
  },
  buildPath: function (ctx, shape) {
    // const { x, y, width, height, r } = shape;
    var height = shape.height;
    var width = shape.width;
    var x = shape.x;
    var y = shape.y;
    var r = shape.r;
    var offsetY = shape.offsetY;
    var offsetX = shape.offsetX;
    var offsetWidth = shape.offsetWidth;
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + width - r, y);
    ctx.arc(x + width - r, y + r, r, -Math.PI / 2, 0);
    ctx.lineTo(x + width, y + height - r);
    ctx.arc(x + width - r, y + height - r, r, 0, Math.PI / 2);
    ctx.lineTo(x + r, y + height);
    // ctx.arc(x + r, y + height - r, r, Math.PI / 2, Math.PI);
    ctx.lineTo(x - offsetWidth, y + height + offsetY);
    ctx.lineTo(x, y + height - offsetX);
    ctx.lineTo(x, y + r);
    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
  }
});
var LabelLowerRight = graphic.Path.extend({
  type: 'labelLowerRight',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    r: 0,
    offsetY: 0,
    offsetX: 0,
    offsetWidth: 0
  },
  buildPath: function (ctx, shape) {
    // const { x, y, width, height, r } = shape;
    var offsetY = shape.offsetY;
    var offsetX = shape.offsetX;
    var offsetWidth = shape.offsetWidth;
    var height = shape.height;
    var width = shape.width;
    var x = shape.x;
    var y = shape.y;
    var r = shape.r;
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + width - r, y);
    ctx.arc(x + width - r, y + r, r, -Math.PI / 2, 0);
    // ctx.arc(x + width - r, y + height - r, r, 0, Math.PI / 2);
    ctx.lineTo(x + width, y + height - offsetWidth);
    ctx.lineTo(x + width + offsetX, y + height + offsetY);
    ctx.lineTo(x + width - r, y + height);
    ctx.lineTo(x + r, y + height);
    ctx.arc(x + r, y + height - r, r, Math.PI / 2, Math.PI);
    ctx.lineTo(x, y + r);
    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
  }
});
var LabelUpperLeft = graphic.Path.extend({
  type: 'labelUpperLeft',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    r: 0,
    offsetY: 0,
    offsetX: 0,
    offsetWidth: 0
  },
  buildPath: function (ctx, shape) {
    var height = shape.height;
    var width = shape.width;
    var x = shape.x;
    var y = shape.y;
    var r = shape.r;
    var offsetY = shape.offsetY;
    var offsetX = shape.offsetX;
    var offsetWidth = shape.offsetWidth;
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + width - r, y);
    ctx.arc(x + width - r, y + r, r, -Math.PI / 2, 0);
    ctx.lineTo(x + width, y + height - r);
    ctx.arc(x + width - r, y + height - r, r, 0, Math.PI / 2);
    ctx.lineTo(x + r, y + height);
    ctx.arc(x + r, y + height - r, r, Math.PI / 2, Math.PI);
    ctx.lineTo(x, y + offsetWidth);
    // ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
    ctx.lineTo(x - offsetX, y - offsetY);
    ctx.lineTo(x + r, y);
  }
});
var LabelUpperRight = graphic.Path.extend({
  type: 'labelUpperRight',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    r: 0,
    offsetY: 0,
    offsetX: 0,
    offsetWidth: 0
  },
  buildPath: function (ctx, shape) {
    var height = shape.height;
    var width = shape.width;
    var x = shape.x;
    var y = shape.y;
    var r = shape.r;
    var offsetY = shape.offsetY;
    var offsetX = shape.offsetX;
    var offsetWidth = shape.offsetWidth;
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + width - r, y);
    ctx.lineTo(x + width + offsetX, y - offsetY);
    ctx.lineTo(x + width, y + offsetWidth);
    // ctx.arc(x + width - r, y + r, r, -Math.PI / 2, 0);
    ctx.lineTo(x + width, y + height - r);
    ctx.arc(x + width - r, y + height - r, r, 0, Math.PI / 2);
    ctx.lineTo(x + r, y + height);
    ctx.arc(x + r, y + height - r, r, Math.PI / 2, Math.PI);
    ctx.lineTo(x, y);
    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
  }
});
var LabelCenter = graphic.Path.extend({
  type: 'labelCenter',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    r: 0
  },
  buildPath: function (ctx, shape) {
    var height = shape.height;
    var width = shape.width;
    var x = shape.x;
    var y = shape.y;
    var r = shape.r;
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + width - r, y);
    ctx.arc(x + width - r, y + r, r, -Math.PI / 2, 0);
    ctx.lineTo(x + width, y + height - r);
    ctx.arc(x + width - r, y + height - r, r, 0, Math.PI / 2);
    ctx.lineTo(x + r, y + height);
    ctx.arc(x + r, y + height - r, r, Math.PI / 2, Math.PI);
    ctx.lineTo(x, y);
    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
  }
});
var XCross = graphic.Path.extend({
  type: 'xCross',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0
  },
  buildPath: function (ctx, shape) {
    var x = shape.x,
      y = shape.y;
    var width = shape.width / 2;
    var height = shape.height / 2;
    // const lineWidth = 0.2;
    ctx.moveTo(x + width, y - height);
    ctx.lineTo(x - width, y + height);
    // ctx.lineTo(x - width + lineWidth, y + height);
    // ctx.lineTo(x + width + lineWidth, y - height);
    // ctx.lineTo(x + width, y - height);
    ctx.moveTo(x - width, y - height);
    ctx.lineTo(x + width, y + height);
    // ctx.lineTo(x + width + lineWidth, y + height);
    // ctx.lineTo(x - width + lineWidth, y - height);
    // ctx.lineTo(x - width, y - height);
  }
});

var LCross = graphic.Path.extend({
  type: 'lCross',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0
  },
  buildPath: function (ctx, shape) {
    var x = shape.x,
      y = shape.y;
    var width = shape.width / 2;
    var height = shape.height / 2;
    ctx.moveTo(x, y - height);
    ctx.lineTo(x, y + height);
    ctx.moveTo(x - width, y);
    ctx.lineTo(x + width, y);
    // ctx.lineTo(x + width + lineWidth, y + height);
    // ctx.lineTo(x - width + lineWidth, y - height);
    // ctx.lineTo(x - width, y - height);
  }
});

var Flag = graphic.Path.extend({
  type: 'flag',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0
  },
  buildPath: function (ctx, shape) {
    var x = shape.x,
      y = shape.y;
    var width = shape.width / 2;
    var height = shape.height / 2;
    var rectWidth = width * 0.2;
    var range = height * 0.6;
    var rangeHeight = height;
    var startX = x - width + rectWidth;
    var endX = x + width;
    var topY = y - height;
    var bottomY = y + height;
    ctx.moveTo(x - width, topY);
    ctx.lineTo(startX, topY);
    ctx.bezierCurveTo(startX + 1 / 3 * shape.width, topY - range, startX + 2 / 3 * shape.width, topY + range, endX, topY);
    ctx.lineTo(endX, topY + rangeHeight);
    ctx.bezierCurveTo(startX + 2 / 3 * shape.width, topY + range + rangeHeight, startX + 1 / 3 * shape.width, topY - range + rangeHeight, startX, topY + rangeHeight);
    ctx.lineTo(startX, bottomY);
    ctx.lineTo(x - width, bottomY);
    ctx.lineTo(x - width, topY);
  }
});
var TriangleDown = graphic.Path.extend({
  type: 'triangleDown',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0
  },
  buildPath: function (path, shape) {
    var cx = shape.cx;
    var cy = shape.cy;
    var width = shape.width / 2;
    var height = shape.height / 2;
    path.moveTo(cx, cy + height);
    path.lineTo(cx + width, cy - height);
    path.lineTo(cx - width, cy - height);
    path.closePath();
  }
});
var TriangleLeft = graphic.Path.extend({
  type: 'triangleLeft',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0
  },
  buildPath: function (path, shape) {
    var cx = shape.cx;
    var cy = shape.cy;
    var width = shape.width / 2;
    var height = shape.height / 2;
    path.moveTo(cx + width, cy + height);
    path.lineTo(cx + width, cy - height);
    path.lineTo(cx - width, cy);
    path.closePath();
  }
});
var LineTriangleLeft = graphic.Path.extend({
  type: 'lineTriangleLeft',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0
  },
  buildPath: function (path, shape) {
    var cx = shape.cx;
    var cy = shape.cy;
    var width = shape.width / 2;
    var height = shape.height / 2;
    var lineWidth = 2;
    path.moveTo(cx + width, cy + height);
    path.lineTo(cx - width, cy);
    path.lineTo(cx + width, cy - height);
    path.lineTo(cx + width + lineWidth, cy - height + lineWidth);
    path.lineTo(cx - width + lineWidth + 2, cy);
    path.lineTo(cx + width + lineWidth, cy + height - lineWidth);
    path.lineTo(cx + width, cy + height);
    // path.closePath();
  }
});

var TriangleRight = graphic.Path.extend({
  type: 'triangleRight',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0
  },
  buildPath: function (path, shape) {
    var cx = shape.cx;
    var cy = shape.cy;
    var width = shape.width / 2;
    var height = shape.height / 2;
    path.moveTo(cx - width, cy + height);
    path.lineTo(cx - width, cy - height);
    path.lineTo(cx + width, cy);
    path.closePath();
  }
});
var LineTriangleRight = graphic.Path.extend({
  type: 'lineTriangleRight',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0
  },
  buildPath: function (path, shape) {
    var cx = shape.cx;
    var cy = shape.cy;
    var width = shape.width / 2;
    var height = shape.height / 2;
    var lineWidth = 2;
    path.moveTo(cx - width, cy + height);
    path.lineTo(cx + width, cy);
    path.lineTo(cx - width, cy - height);
    path.lineTo(cx - width - lineWidth, cy - height + lineWidth);
    path.lineTo(cx + width - lineWidth - 2, cy);
    path.lineTo(cx - width - lineWidth, cy + height - lineWidth);
    path.lineTo(cx - width, cy + height);
    // path.closePath();
  }
});

var ArrowUp = graphic.Path.extend({
  type: 'arrowUp',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0,
    rectWidth: 0,
    triangleHeight: 0
  },
  buildPath: function (ctx, shape) {
    var cx = shape.cx,
      cy = shape.cy,
      rectWidth = shape.rectWidth,
      triangleHeight = shape.triangleHeight;
    var width = shape.width / 2;
    var height = shape.height / 2;
    var triangleY = cy - height + triangleHeight;
    ctx.moveTo(cx, cy - height);
    ctx.lineTo(cx + width, triangleY);
    ctx.lineTo(cx + width - rectWidth, triangleY);
    ctx.lineTo(cx + width - rectWidth, cy + height);
    ctx.lineTo(cx - width + rectWidth, cy + height);
    ctx.lineTo(cx - width + rectWidth, triangleY);
    ctx.lineTo(cx - width, triangleY);
    ctx.lineTo(cx, cy - height);
    // ctx.closePath();
  }
});

var marginArrow = 4;
var LineArrowUp = graphic.Path.extend({
  type: 'lineArrowUp',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0,
    triangleHeight: 0,
    count: 1
  },
  buildPath: function (ctx, shape) {
    var cx = shape.cx,
      cy = shape.cy,
      triangleHeight = shape.triangleHeight,
      count = shape.count;
    var width = shape.width / 2;
    var height = shape.height / 2;
    var baseY = cy;
    for (var index = 0; index < count; index++) {
      var triangleY = baseY - height + triangleHeight;
      ctx.moveTo(cx + width, triangleY);
      ctx.lineTo(cx, baseY - height);
      ctx.lineTo(cx - width, triangleY);
      baseY = baseY + marginArrow;
    }
    ctx.moveTo(cx, baseY - height - marginArrow);
    ctx.lineTo(cx, baseY + height - marginArrow);
    // ctx.closePath();
  }
});

var ArrowUpClose = graphic.Path.extend({
  type: 'arrowUpClose',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0,
    rectWidth: 0,
    triangleHeight: 0
  },
  buildPath: function (ctx, shape) {
    var cx = shape.cx,
      cy = shape.cy,
      rectWidth = shape.rectWidth,
      triangleHeight = shape.triangleHeight;
    var width = shape.width / 2;
    var height = shape.height / 2;
    var triangleY = cy - height + triangleHeight;
    var rectHeight = 3;
    ctx.moveTo(cx, cy - height);
    ctx.lineTo(cx + width, triangleY);
    ctx.lineTo(cx + width - rectWidth, triangleY);
    ctx.lineTo(cx + width - rectWidth, cy + height);
    ctx.lineTo(cx - width + rectWidth, cy + height);
    ctx.lineTo(cx - width + rectWidth, triangleY);
    ctx.lineTo(cx - width, triangleY);
    ctx.lineTo(cx, cy - height);
    // ctx.closePath();
    ctx.rect(cx - width + 0.5, cy - height - 0.5 - rectHeight, shape.width - 0.5, rectHeight);
  }
});
var ArrowDown = graphic.Path.extend({
  type: 'arrowDown',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0,
    rectWidth: 0,
    triangleHeight: 0
  },
  buildPath: function (ctx, shape) {
    var cx = shape.cx,
      cy = shape.cy,
      rectWidth = shape.rectWidth,
      triangleHeight = shape.triangleHeight;
    var width = shape.width / 2;
    var height = shape.height / 2;
    var triangleY = cy + height - triangleHeight;
    ctx.moveTo(cx, cy + height);
    ctx.lineTo(cx + width, triangleY);
    ctx.lineTo(cx + width - rectWidth, triangleY);
    ctx.lineTo(cx + width - rectWidth, cy - height);
    ctx.lineTo(cx - width + rectWidth, cy - height);
    ctx.lineTo(cx - width + rectWidth, triangleY);
    ctx.lineTo(cx - width, triangleY);
    ctx.lineTo(cx, cy + height);
    // ctx.closePath();
  }
});

var LineArrowDown = graphic.Path.extend({
  type: 'lineArrowDown',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0,
    triangleHeight: 0,
    count: 1
  },
  buildPath: function (ctx, shape) {
    var cx = shape.cx,
      cy = shape.cy,
      triangleHeight = shape.triangleHeight,
      count = shape.count;
    var width = shape.width / 2;
    var height = shape.height / 2;
    var baseY = cy;
    for (var index = 0; index < count; index++) {
      var triangleY = baseY + height - triangleHeight;
      ctx.moveTo(cx + width, triangleY);
      ctx.lineTo(cx, baseY + height);
      ctx.lineTo(cx - width, triangleY);
      baseY = baseY - marginArrow;
    }
    ctx.moveTo(cx, baseY + height + marginArrow);
    ctx.lineTo(cx, baseY - height + marginArrow);
    // ctx.closePath();
  }
});

var ArrowDownClose = graphic.Path.extend({
  type: 'arrowDownClose',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0,
    rectWidth: 0,
    triangleHeight: 0
  },
  buildPath: function (ctx, shape) {
    var cx = shape.cx,
      cy = shape.cy,
      rectWidth = shape.rectWidth,
      triangleHeight = shape.triangleHeight;
    var width = shape.width / 2;
    var height = shape.height / 2;
    var triangleY = cy + height - triangleHeight;
    var rectHeight = 3;
    ctx.moveTo(cx, cy + height);
    ctx.lineTo(cx + width, triangleY);
    ctx.lineTo(cx + width - rectWidth, triangleY);
    ctx.lineTo(cx + width - rectWidth, cy - height);
    ctx.lineTo(cx - width + rectWidth, cy - height);
    ctx.lineTo(cx - width + rectWidth, triangleY);
    ctx.lineTo(cx - width, triangleY);
    ctx.lineTo(cx, cy + height);
    // ctx.closePath();
    ctx.rect(cx - width + 0.5, cy + height + 0.5, shape.width - 0.5, rectHeight);
  }
});
/**
 * Map of path constructors
 */
// TODO Use function to build symbol path.
var symbolCtors = {
  line: graphic.Line,
  rect: graphic.Rect,
  roundRect: graphic.Rect,
  square: graphic.Rect,
  circle: graphic.Circle,
  diamond: Diamond,
  pin: Pin,
  arrow: Arrow,
  triangle: Triangle,
  cross: Cross,
  labelCenter: LabelCenter,
  labelDown: LabelDown,
  labelUp: LabelUp,
  labelLeft: LabelLeft,
  labelRight: LabelRight,
  labelLowerLeft: LabelLowerLeft,
  labelLowerRight: LabelLowerRight,
  labelUpperLeft: LabelUpperLeft,
  labelUpperRight: LabelUpperRight,
  xCross: XCross,
  lCross: LCross,
  arrowUp: ArrowUp,
  lineArrowUp: LineArrowUp,
  flag: Flag,
  triangleDown: TriangleDown,
  triangleLeft: TriangleLeft,
  triangleRight: TriangleRight,
  lineTriangleLeft: LineTriangleLeft,
  lineTriangleRight: LineTriangleRight,
  arrowDown: ArrowDown,
  lineArrowDown: LineArrowDown,
  arrowUpClose: ArrowUpClose,
  arrowDownClose: ArrowDownClose
};
// const labelShapeMakers: SymbolShapeMaker = function (x, y, w, h, shape: graphic.Rect['shape']) {
//     shape.x = x;
//     shape.y = y;
//     shape.width = w;
//     shape.height = h;
//     shape.r = w / 10;
// };
var symbolShapeMakers = {
  line: function (x, y, w, h, shape) {
    shape.x1 = x;
    shape.y1 = y + h / 2;
    shape.x2 = x + w;
    shape.y2 = y + h / 2;
  },
  rect: function (x, y, w, h, shape) {
    shape.x = x;
    shape.y = y;
    shape.width = w;
    shape.height = h;
  },
  roundRect: function (x, y, w, h, shape) {
    shape.x = x;
    shape.y = y;
    shape.width = w;
    shape.height = h;
    shape.r = Math.min(w, h) / 4;
  },
  square: function (x, y, w, h, shape) {
    var size = Math.min(w, h);
    shape.x = x;
    shape.y = y;
    shape.width = size;
    shape.height = size;
  },
  circle: function (x, y, w, h, shape) {
    // Put circle in the center of square
    shape.cx = x + w / 2;
    shape.cy = y + h / 2;
    shape.r = Math.min(w, h) / 2;
  },
  diamond: function (x, y, w, h, shape) {
    shape.cx = x + w / 2;
    shape.cy = y + h / 2;
    shape.width = w;
    shape.height = h;
  },
  pin: function (x, y, w, h, shape) {
    shape.x = x + w / 2;
    shape.y = y + h / 2;
    shape.width = w;
    shape.height = h;
  },
  arrow: function (x, y, w, h, shape) {
    shape.x = x + w / 2;
    shape.y = y + h / 2;
    shape.width = w;
    shape.height = h;
  },
  triangle: function (x, y, w, h, shape) {
    shape.cx = x + w / 2;
    shape.cy = y + h / 2;
    shape.width = w;
    shape.height = h;
  },
  cross: function (x, y, w, h, shape) {
    shape.x = x + w / 2;
    shape.y = y + h / 2;
    shape.width = w;
    shape.height = h;
  },
  labelCenter: function (x, y, w, h, shape) {
    var r = 2;
    var offset = 1;
    shape.x = x - w / 2 + offset;
    shape.y = y - h;
    shape.width = w;
    shape.height = h;
    shape.r = r;
  },
  labelDown: function (x, y, w, h, shape, parentShape) {
    var triangleWidth = parentShape.triangleWidth;
    var r = 2;
    var offset = 1;
    shape.triangleWidth = triangleWidth;
    shape.x = x - w / 2 + offset;
    shape.y = y - h - triangleWidth;
    shape.width = w;
    shape.height = h;
    shape.r = r;
  },
  labelUp: function (x, y, w, h, shape, parentShape) {
    var r = 2;
    var offset = 1;
    shape.x = x - w / 2 + offset;
    shape.triangleWidth = parentShape.triangleWidth;
    shape.y = y - h + parentShape.triangleWidth;
    shape.width = w;
    shape.height = h;
    shape.r = r;
  },
  labelLeft: function (x, y, w, h, shape, parentShape) {
    var triangleWidth = parentShape.triangleWidth;
    var r = 2;
    shape.triangleWidth = triangleWidth;
    shape.x = x + triangleWidth;
    shape.y = y - h / 2;
    shape.width = w;
    shape.height = h;
    shape.r = r;
  },
  labelRight: function (x, y, w, h, shape, parentShape) {
    var triangleWidth = parentShape.triangleWidth;
    var r = 2;
    shape.triangleWidth = triangleWidth;
    shape.x = x - w - triangleWidth;
    shape.y = y - h / 2;
    shape.width = w;
    shape.height = h;
    shape.r = r;
  },
  labelLowerLeft: function (x, y, w, h, shape, parentShape) {
    var offsetY = parentShape.offsetY;
    var offsetX = parentShape.offsetX;
    var offsetWidth = parentShape.offsetWidth;
    shape.x = x + offsetWidth;
    shape.y = y - h - offsetY;
    shape.width = w;
    shape.height = h;
    shape.r = 2;
    shape.offsetY = offsetY;
    shape.offsetX = offsetX;
    shape.offsetWidth = offsetWidth;
  },
  labelLowerRight: function (x, y, w, h, shape, parentShape) {
    // const r = 2;
    var offsetY = parentShape.offsetY;
    var offsetX = parentShape.offsetX;
    var offsetWidth = parentShape.offsetWidth;
    shape.x = x - w - offsetX;
    shape.y = y - h - offsetY;
    shape.width = w;
    shape.height = h;
    shape.r = 2;
    shape.offsetY = offsetY;
    shape.offsetX = offsetX;
    shape.offsetWidth = offsetWidth;
  },
  labelUpperLeft: function (x, y, w, h, shape, parentShape) {
    var offsetY = parentShape.offsetY;
    var offsetX = parentShape.offsetX;
    var offsetWidth = parentShape.offsetWidth;
    shape.x = x + offsetX;
    shape.y = y - h + parentShape.offsetY;
    shape.width = w;
    shape.height = h;
    shape.r = 2;
    shape.offsetY = offsetY;
    shape.offsetX = offsetX;
    shape.offsetWidth = offsetWidth;
  },
  labelUpperRight: function (x, y, w, h, shape, parentShape) {
    var offsetY = parentShape.offsetY;
    var offsetX = parentShape.offsetX;
    var offsetWidth = parentShape.offsetWidth;
    shape.x = x - w - offsetX;
    shape.y = y - h + parentShape.offsetY;
    shape.width = w;
    shape.height = h;
    shape.r = 2;
    shape.offsetY = offsetY;
    shape.offsetX = offsetX;
    shape.offsetWidth = offsetWidth;
  },
  xCross: function (x, y, w, h, shape) {
    shape.x = x;
    shape.y = y;
    shape.width = w;
    shape.height = h;
  },
  lCross: function (x, y, w, h, shape) {
    shape.x = x;
    shape.y = y;
    shape.width = w;
    shape.height = h;
  },
  flag: function (x, y, w, h, shape) {
    shape.x = x;
    shape.y = y;
    shape.width = w;
    shape.height = h;
  },
  triangleDown: function (x, y, w, h, shape) {
    shape.cx = x + w / 2;
    shape.cy = y + h / 2;
    shape.width = w;
    shape.height = h;
  },
  triangleLeft: function (x, y, w, h, shape) {
    shape.cx = x + w / 2;
    shape.cy = y;
    shape.width = w;
    shape.height = h;
  },
  triangleRight: function (x, y, w, h, shape) {
    shape.cx = x - w / 2;
    shape.cy = y;
    shape.width = w;
    shape.height = h;
  },
  lineTriangleLeft: function (x, y, w, h, shape) {
    shape.cx = x + w / 2;
    shape.cy = y;
    shape.width = w;
    shape.height = h;
  },
  lineTriangleRight: function (x, y, w, h, shape) {
    shape.cx = x - w / 2;
    shape.cy = y;
    shape.width = w;
    shape.height = h;
  },
  arrowUp: function (x, y, w, h, shape, parentShape) {
    shape.rectWidth = parentShape.triangleWidth;
    shape.triangleHeight = parentShape.triangleHeight;
    shape.cx = x;
    shape.cy = y;
    shape.width = w;
    shape.height = h;
  },
  lineArrowUp: function (x, y, w, h, shape, parentShape) {
    shape.triangleHeight = parentShape.triangleHeight;
    shape.count = parentShape.count;
    shape.cx = x;
    shape.cy = y;
    shape.width = w;
    shape.height = h;
  },
  arrowDown: function (x, y, w, h, shape, parentShape) {
    shape.rectWidth = parentShape.triangleWidth;
    shape.triangleHeight = parentShape.triangleHeight;
    shape.cx = x;
    shape.cy = y;
    shape.width = w;
    shape.height = h;
  },
  lineArrowDown: function (x, y, w, h, shape, parentShape) {
    shape.triangleHeight = parentShape.triangleHeight;
    shape.count = parentShape.count;
    shape.cx = x;
    shape.cy = y;
    shape.width = w;
    shape.height = h;
  },
  arrowUpClose: function (x, y, w, h, shape, parentShape) {
    shape.rectWidth = parentShape.triangleWidth;
    shape.triangleHeight = parentShape.triangleHeight;
    shape.cx = x;
    shape.cy = y;
    shape.width = w;
    shape.height = h;
  },
  arrowDownClose: function (x, y, w, h, shape, parentShape) {
    shape.rectWidth = parentShape.triangleWidth;
    shape.triangleHeight = parentShape.triangleHeight;
    shape.cx = x;
    shape.cy = y;
    shape.width = w;
    shape.height = h;
  }
};
export var symbolBuildProxies = {};
each(symbolCtors, function (Ctor, name) {
  symbolBuildProxies[name] = new Ctor();
});
var SymbolClz = graphic.Path.extend({
  type: 'symbol',
  shape: {
    symbolType: '',
    x: 0,
    y: 0,
    width: 0,
    height: 0
  },
  calculateTextPosition: function (out, config, rect) {
    var res = calculateTextPosition(out, config, rect);
    var shape = this.shape;
    if (shape && shape.symbolType === 'pin' && config.position === 'inside') {
      res.y = rect.y + rect.height * 0.4;
    }
    return res;
  },
  buildPath: function (ctx, shape, inBundle) {
    var symbolType = shape.symbolType;
    if (symbolType !== 'none') {
      var proxySymbol = symbolBuildProxies[symbolType];
      if (!proxySymbol) {
        // Default rect
        symbolType = 'rect';
        proxySymbol = symbolBuildProxies[symbolType];
      }
      symbolShapeMakers[symbolType](shape.x, shape.y, shape.width, shape.height, proxySymbol.shape, shape);
      proxySymbol.buildPath(ctx, proxySymbol.shape, inBundle);
    }
  }
});
// Provide setColor helper method to avoid determine if set the fill or stroke outside
function symbolPathSetColor(color, innerColor) {
  if (this.type !== 'image') {
    var symbolStyle = this.style;
    if (this.__isEmptyBrush) {
      symbolStyle.stroke = color;
      symbolStyle.fill = innerColor || '#fff';
      // TODO Same width with lineStyle in LineView
      symbolStyle.lineWidth = 2;
    } else if (this.shape.symbolType === 'line') {
      symbolStyle.stroke = color;
    } else {
      symbolStyle.fill = color;
    }
    this.markRedraw();
  }
}
/**
 * Create a symbol element with given symbol configuration: shape, x, y, width, height, color
 */
export function createSymbol(symbolType, x, y, w, h, color,
// whether to keep the ratio of w/h,
keepAspect) {
  // TODO Support image object, DynamicImage.
  var isEmpty = symbolType.indexOf('empty') === 0;
  if (isEmpty) {
    symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6);
  }
  var symbolPath;
  if (symbolType.indexOf('image://') === 0) {
    symbolPath = graphic.makeImage(symbolType.slice(8), new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover');
  } else if (symbolType.indexOf('path://') === 0) {
    symbolPath = graphic.makePath(symbolType.slice(7), {}, new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover');
  } else {
    symbolPath = new SymbolClz({
      shape: {
        symbolType: symbolType,
        x: x,
        y: y,
        width: w,
        height: h
      }
    });
  }
  symbolPath.__isEmptyBrush = isEmpty;
  // TODO Should deprecate setColor
  symbolPath.setColor = symbolPathSetColor;
  if (color) {
    symbolPath.setColor(color);
  }
  return symbolPath;
}
export function normalizeSymbolSize(symbolSize) {
  if (!isArray(symbolSize)) {
    symbolSize = [+symbolSize, +symbolSize];
  }
  return [symbolSize[0] || 0, symbolSize[1] || 0];
}
export function normalizeSymbolOffset(symbolOffset, symbolSize) {
  if (symbolOffset == null) {
    return;
  }
  if (!isArray(symbolOffset)) {
    symbolOffset = [symbolOffset, symbolOffset];
  }
  return [parsePercent(symbolOffset[0], symbolSize[0]) || 0, parsePercent(retrieve2(symbolOffset[1], symbolOffset[0]), symbolSize[1]) || 0];
}