text: 'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.default = void 0;
  
  var _Path = require("../drawing/Path");
  
  var _textDecoration = require("../parsing/textDecoration");
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
  
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  
  var addColorStops = function addColorStops(gradient, canvasGradient) {
    var maxStop = Math.max.apply(null, gradient.colorStops.map(function (colorStop) {
      return colorStop.stop;
    }));
    var f = 1 / Math.max(1, maxStop);
    gradient.colorStops.forEach(function (colorStop) {
      canvasGradient.addColorStop(Math.floor(Math.max(0, f * colorStop.stop)), colorStop.color.toString());
    });
  };
  
  var CanvasRenderer =
  /*#__PURE__*/
  function () {
    function CanvasRenderer(canvas) {
      _classCallCheck(this, CanvasRenderer);
  
      this.canvas = canvas ? canvas : document.createElement('canvas');
    }
  
    _createClass(CanvasRenderer, [{
      key: "render",
      value: function render(options) {
        this.ctx = this.canvas.getContext('2d');
        this.options = options;
        this.canvas.width = Math.floor(options.width * options.scale);
        this.canvas.height = Math.floor(options.height * options.scale);
        this.canvas.style.width = "".concat(options.width, "px");
        this.canvas.style.height = "".concat(options.height, "px");
        this.ctx.scale(this.options.scale, this.options.scale);
        this.ctx.translate(-options.x, -options.y);
        this.ctx.textBaseline = 'bottom';
        options.logger.log("Canvas renderer initialized (".concat(options.width, "x").concat(options.height, " at ").concat(options.x, ",").concat(options.y, ") with scale ").concat(this.options.scale));
      }
    }, {
      key: "clip",
      value: function clip(clipPaths, callback) {
        var _this = this;
  
        if (clipPaths.length) {
          this.ctx.save();
          clipPaths.forEach(function (path) {
            _this.path(path);
  
            _this.ctx.clip();
          });
        }
  
        callback();
  
        if (clipPaths.length) {
          this.ctx.restore();
        }
      }
    }, {
      key: "drawImage",
      value: function drawImage(image, source, destination) {
        this.ctx.drawImage(image, source.left, source.top, source.width, source.height, destination.left, destination.top, destination.width, destination.height);
      }
    }, {
      key: "drawShape",
      value: function drawShape(path, color) {
        this.path(path);
        this.ctx.fillStyle = color.toString();
        this.ctx.fill();
      }
    }, {
      key: "fill",
      value: function fill(color) {
        this.ctx.fillStyle = color.toString();
        this.ctx.fill();
      }
    }, {
      key: "getTarget",
      value: function getTarget() {
        this.canvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0);
        return Promise.resolve(this.canvas);
      }
    }, {
      key: "path",
      value: function path(_path) {
        var _this2 = this;
  
        this.ctx.beginPath();
  
        if (Array.isArray(_path)) {
          _path.forEach(function (point, index) {
            var start = point.type === _Path.PATH.VECTOR ? point : point.start;
  
            if (index === 0) {
              _this2.ctx.moveTo(start.x, start.y);
            } else {
              _this2.ctx.lineTo(start.x, start.y);
            }
  
            if (point.type === _Path.PATH.BEZIER_CURVE) {
              _this2.ctx.bezierCurveTo(point.startControl.x, point.startControl.y, point.endControl.x, point.endControl.y, point.end.x, point.end.y);
            }
          });
        } else {
          this.ctx.arc(_path.x + _path.radius, _path.y + _path.radius, _path.radius, 0, Math.PI * 2, true);
        }
  
        this.ctx.closePath();
      }
    }, {
      key: "rectangle",
      value: function rectangle(x, y, width, height, color) {
        this.ctx.fillStyle = color.toString();
        this.ctx.fillRect(x, y, width, height);
      }
    }, {
      key: "renderLinearGradient",
      value: function renderLinearGradient(bounds, gradient) {
        var linearGradient = this.ctx.createLinearGradient(bounds.left + gradient.direction.x1, bounds.top + gradient.direction.y1, bounds.left + gradient.direction.x0, bounds.top + gradient.direction.y0);
        addColorStops(gradient, linearGradient);
        this.ctx.fillStyle = linearGradient;
        this.ctx.fillRect(bounds.left, bounds.top, bounds.width, bounds.height);
      }
    }, {
      key: "renderRadialGradient",
      value: function renderRadialGradient(bounds, gradient) {
        var _this3 = this;
  
        var x = bounds.left + gradient.center.x;
        var y = bounds.top + gradient.center.y;
        var radialGradient = this.ctx.createRadialGradient(x, y, 0, x, y, gradient.radius.x);
  
        if (!radialGradient) {
          return;
        }
  
        addColorStops(gradient, radialGradient);
        this.ctx.fillStyle = radialGradient;
  
        if (gradient.radius.x !== gradient.radius.y) {
          // transforms for elliptical radial gradient
          var midX = bounds.left + 0.5 * bounds.width;
          var midY = bounds.top + 0.5 * bounds.height;
          var f = gradient.radius.y / gradient.radius.x;
          var invF = 1 / f;
          this.transform(midX, midY, [1, 0, 0, f, 0, 0], function () {
            return _this3.ctx.fillRect(bounds.left, invF * (bounds.top - midY) + midY, bounds.width, bounds.height * invF);
          });
        } else {
          this.ctx.fillRect(bounds.left, bounds.top, bounds.width, bounds.height);
        }
      }
    }, {
      key: "renderRepeat",
      value: function renderRepeat(path, image, imageSize, offsetX, offsetY) {
        this.path(path);
        this.ctx.fillStyle = this.ctx.createPattern(this.resizeImage(image, imageSize), 'repeat');
        this.ctx.translate(offsetX, offsetY);
        this.ctx.fill();
        this.ctx.translate(-offsetX, -offsetY);
      }
    }, {
      key: "renderTextNode",
      value: function renderTextNode(textBounds, color, font, textDecoration, textShadows) {
        var _this4 = this;
  
        this.ctx.font = [font.fontStyle, font.fontVariant, font.fontWeight, font.fontSize, font.fontFamily].join(' ');
        textBounds.forEach(function (text) {
          _this4.ctx.fillStyle = color.toString();
  
          if (textShadows && text.text.trim().length) {
            textShadows.slice(0).reverse().forEach(function (textShadow) {
              _this4.ctx.shadowColor = textShadow.color.toString();
              _this4.ctx.shadowOffsetX = textShadow.offsetX * _this4.options.scale;
              _this4.ctx.shadowOffsetY = textShadow.offsetY * _this4.options.scale;
              _this4.ctx.shadowBlur = textShadow.blur;
  
              _this4.ctx.fillText(text.text, text.bounds.left, text.bounds.top + text.bounds.height);
            });
            _this4.ctx.shadowColor = '';
            _this4.ctx.shadowOffsetX = 0;
            _this4.ctx.shadowOffsetY = 0;
            _this4.ctx.shadowBlur = 0;
          } else {
            _this4.ctx.fillText(text.text, text.bounds.left, text.bounds.top + text.bounds.height);
          }
  
          if (textDecoration !== null) {
            var textDecorationColor = textDecoration.textDecorationColor || color;
            textDecoration.textDecorationLine.forEach(function (textDecorationLine) {
              switch (textDecorationLine) {
                case _textDecoration.TEXT_DECORATION_LINE.UNDERLINE:
                  // Draws a line at the baseline of the font
                  // TODO As some browsers display the line as more than 1px if the font-size is big,
                  // need to take that into account both in position and size
                  var _this4$options$fontMe = _this4.options.fontMetrics.getMetrics(font),
                      baseline = _this4$options$fontMe.baseline;
  
                  _this4.rectangle(text.bounds.left, Math.round(text.bounds.top + baseline), text.bounds.width, 1, textDecorationColor);
  
                  break;
  
                case _textDecoration.TEXT_DECORATION_LINE.OVERLINE:
                  _this4.rectangle(text.bounds.left, Math.round(text.bounds.top), text.bounds.width, 1, textDecorationColor);
  
                  break;
  
                case _textDecoration.TEXT_DECORATION_LINE.LINE_THROUGH:
                  // TODO try and find exact position for line-through
                  var _this4$options$fontMe2 = _this4.options.fontMetrics.getMetrics(font),
                      middle = _this4$options$fontMe2.middle;
  
                  _this4.rectangle(text.bounds.left, Math.ceil(text.bounds.top + middle), text.bounds.width, 1, textDecorationColor);
  
                  break;
              }
            });
          }
        });
      }
    }, {
      key: "resizeImage",
      value: function resizeImage(image, size) {
        if (image.width === size.width && image.height === size.height) {
          return image;
        }
  
        var canvas = this.canvas.ownerDocument.createElement('canvas');
        canvas.width = size.width;
        canvas.height = size.height;
        var ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, size.width, size.height);
        return canvas;
      }
    }, {
      key: "setOpacity",
      value: function setOpacity(opacity) {
        this.ctx.globalAlpha = opacity;
      }
    }, {
      key: "transform",
      value: function transform(offsetX, offsetY, matrix, callback) {
        this.ctx.save();
        this.ctx.translate(offsetX, offsetY);
        this.ctx.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
        this.ctx.translate(-offsetX, -offsetY);
        callback();
        this.ctx.restore();
      }
    }]);
  
    return CanvasRenderer;
  }();
  
  exports.default = CanvasRenderer;
  module.exports = exports.default;