Converts the options to the Canvas options format

@param {drawingOptions} options The drawing options
@return {canvasDrawingOptions} The converted options
497294
function (options) {
            var convertedOptions = {};

            if ('fillColor' in options) {
                convertedOptions.fillStyle = MathLib.colorConvert(options.fillColor);
            } else if ('color' in options) {
                convertedOptions.fillStyle = MathLib.colorConvert(options.color);
            }

            if ('font' in options) {
                convertedOptions.font = options.font;
            }

            if ('fontSize' in options) {
                convertedOptions.fontSize = options.fontSize;
            }

            if ('lineColor' in options) {
                convertedOptions.strokeStyle = MathLib.colorConvert(options.lineColor);
            } else if ('color' in options) {
                convertedOptions.strokeStyle = MathLib.colorConvert(options.color);
            }

            return convertedOptions;
        }
1084342
function renderChoices(choices, pointer) {
  var output = '';

  choices.forEach(function(choice, i) {
    output += '\n  ';

    if (choice.type === 'separator') {
      output += ' ' + choice;
      return;
    }

    var choiceStr = choice.key + ') ' + choice.name;
    if (pointer === choice.key) {
      choiceStr = utils.chalk.cyan(choiceStr);
    }
    output += choiceStr;
  });

  return output;
}
1373413
function (options) {

    var
      context     = options.context,
      lineWidth   = options.lineWidth,
      shadowSize  = options.shadowSize,
      offset;

    context.save();
    context.lineJoin = 'round';

    if (shadowSize) {

      context.lineWidth = shadowSize / 2;
      offset = lineWidth / 2 + context.lineWidth / 2;
      
      // @TODO do this instead with a linear gradient
      context.strokeStyle = "rgba(0,0,0,0.1)";
      this.plot(options, offset + shadowSize / 2, false);

      context.strokeStyle = "rgba(0,0,0,0.2)";
      this.plot(options, offset, false);
    }

    context.lineWidth = lineWidth;
    context.strokeStyle = options.color;

    this.plot(options, 0, true);

    context.restore();
  }
711611
function createOptions( options ) {
    var object = optionsCache[ options ] = {};
    _each( options.split( /\s+/ ), function( flag ) {
      object[ flag ] = true;
    });
    return object;
  }
731386
function (imageOptions) {

		imageOptions = imageOptions || {};

		var patternGuid = L.Util.guid();

		var radius = this.options.radius || Math.max(this.options.radiusX, this.options.radiusY);
		var diameter = this._getDefaultDiameter(radius);
		var imageSize = imageOptions.imageSize || new L.Point(diameter, diameter);

		var circleSize = imageOptions.radius || diameter/2;

		var shapeOptions = imageOptions.shape || {
			circle: {
				r: circleSize,
				cx: 0,
				cy: 0
			}
		};

		var patternOptions = imageOptions.pattern || {
			width: imageSize.x,
			height: imageSize.y,
			x: 0,
			y: 0
		};

		var shapeKeys = Object.keys(shapeOptions);
		var shapeType = shapeKeys.length > 0 ? shapeKeys[0] : 'circle';

		shapeOptions[shapeType].fill = 'url(#' + patternGuid + ')';

		var shape = this._createShape(shapeType, shapeOptions[shapeType]);

		if (this.options.clickable) {
			shape.setAttribute('class', 'leaflet-clickable');
		}

		patternOptions.id = patternGuid;
		patternOptions.patternUnits = patternOptions.patternUnits || 'objectBoundingBox';

		var pattern = this._createPattern(patternOptions);

		imageOptions = imageOptions.image || {
			width: imageSize.x,
			height: imageSize.y,
			x: 0,
			y: 0,
			url: this.options.imageCircleUrl
		};

		var image = this._createImage(imageOptions);
        image.setAttributeNS(L.Path.XLINK_NS, 'xlink:href', imageOptions.url);

		pattern.appendChild(image);
		this._defs.appendChild(pattern);
		this._container.insertBefore(shape, this._defs);

		this._shape = shape;
		
		var me = this;
		
		this._shape.addEventListener('mouseover', function () {
			me.fire('mouseover');
		});
		
		this._shape.addEventListener('mouseout', function () {
			me.fire('mouseout');
		});
		
		this._shape.addEventListener('mousemove', function () {
			me.fire('mousemove');
		});
		
		var anchorPoint = this.getTextAnchor();

		if (this._shape && anchorPoint) {
			if (this._shape.tagName === 'circle' || this._shape.tagName === 'ellipse') {
				this._shape.setAttribute('cx', anchorPoint.x);
				this._shape.setAttribute('cy', anchorPoint.y);
			}
			else {
				var width = this._shape.getAttribute('width');
				var height = this._shape.getAttribute('height');
				this._shape.setAttribute('x', anchorPoint.x - Number(width)/2);
				this._shape.setAttribute('y', anchorPoint.y - Number(height)/2);
			}
		}
	}
1030108
function renderChoices(choices, pointer) {
  var output = '';
  var separatorOffset = 0;

  choices.forEach(function(choice, i) {
    if (choice.type === 'separator') {
      separatorOffset++;
      output += ' ' + choice + '\n';
      return;
    }

    if (choice.disabled) {
      separatorOffset++;
      output += ' - ' + choice.name;
      output += ' (' + (typeof choice.disabled === 'string' ? choice.disabled : 'Disabled') + ')';
    } else {
      var isSelected = (i - separatorOffset === pointer);
      output += isSelected ? utils.chalk.cyan(utils.figures.pointer) : ' ';
      output += getCheckbox(choice.checked) + ' ' + choice.name;
    }

    output += '\n';
  });

  return output.replace(/\n$/, '');
}
138373
def draw
      drawns = []
      @options[:include].each { |n| drawns << n } unless @options[:include].nil?
      count = @options[:include] ? @options[:pick] - @options[:include].count : @options[:pick]
      count.times { drawns << pick(drawns) }
      drawns
    end
682430
function drawRadialTitle(context, options) {
    if (!options.title) return;

    context.save();
    context.font = drawings.font(options, 'Title', context.max / 200);
    context.fillStyle = options.colorTitle;
    context.textAlign = 'center';
    context.fillText(options.title, 0, -context.max / 4.25, context.max * 0.8);
    context.restore();
}
246132
function (options) {
    options = options || {}
    this.isTTY = process.stdout.isTTY || false
    this.useColors = options.useColors || this.isTTY
}
374711
function (options) {
    if (morpheus.Util.isHeadless()) {
      // hack to force creation of color scheme
      for (var i = 0, length = this.rowTracks.length; i < length; i++) {
        var track = this.rowTracks[i];
        track.setInvalid(true);
        if (track.isVisible()) {
          track.paint({
            x: 0,
            y: 0,
            height: 10,
            width: 10
          });
        }
      }
      for (var i = 0, length = this.columnTracks.length; i < length; i++) {
        var track = this.columnTracks[i];
        track.setInvalid(true);
        if (track.isVisible()) {
          track.paint({
            x: 0,
            y: 0,
            height: 10,
            width: 10
          });
        }
      }
      return;
    }
    options = $.extend({}, {
      paint: true
    }, options);
    this.updatingScroll = true;
    var availableHeight = this.getAvailableHeight();
    var availableWidth = this.getAvailableWidth();
    var heatmapPrefSize = this.heatmap.getPreferredSize();

    var columnDendrogramHeight = 0;
    var rowDendrogramWidth = 0;
    if (this.columnDendrogram) {
      columnDendrogramHeight = morpheus.CanvasUtil.getPreferredSize(this.columnDendrogram).height;
    }
    if (this.rowDendrogram) {
      rowDendrogramWidth = morpheus.CanvasUtil.getPreferredSize(this.rowDendrogram).width;
    }
    var rowTrackWidthSum = 0;
    for (var i = 0, length = this.rowTracks.length; i < length; i++) {
      if (this.rowTracks[i].isVisible()) {
        // was manually resized
        if (this.rowTracks[i].getPrefWidth() !== undefined) {
          this.rowTrackHeaders[i].setPrefWidth(this.rowTracks[i].getPrefWidth());
        }
        rowTrackWidthSum += Math.max(morpheus.CanvasUtil.getPreferredSize(this.rowTrackHeaders[i]).width,
          morpheus.CanvasUtil.getPreferredSize(this.rowTracks[i]).width);
      }
    }
    if (availableWidth !== -1 && (rowTrackWidthSum + rowDendrogramWidth + heatmapPrefSize.width) > availableWidth) {
      // shrink row tracks
      //var over = (rowTrackWidthSum + rowDendrogramWidth + heatmapPrefSize.width) - availableWidth;
      rowTrackWidthSum = 0;
      for (var i = 0, length = this.rowTracks.length; i < length; i++) {
        if (this.rowTracks[i].isVisible()) {
          var rowTrackHeaderSize = morpheus.CanvasUtil.getPreferredSize(this.rowTrackHeaders[i]);
          var width = Math.max(rowTrackHeaderSize.width, morpheus.CanvasUtil.getPreferredSize(this.rowTracks[i]).width);
          if (!rowTrackHeaderSize.widthSet) {
            width = Math.min(400, width);
            this.rowTracks[i].setPrefWidth(width);
            this.rowTrackHeaders[i].setPrefWidth(width);
          }
          rowTrackWidthSum += width;
        }
      }
    }

    var ypos = columnDendrogramHeight;
    var maxHeaderWidth = 0;
    // get max column header width
    for (var i = 0, length = this.columnTracks.length; i < length; i++) {
      if (this.columnTracks[i].isVisible()) {
        if (this.columnTracks[i].getPrefHeight() !== undefined) {
          this.columnTrackHeaders[i].setPrefHeight(this.columnTracks[i].getPrefHeight());
        }
        var width = morpheus.CanvasUtil.getPreferredSize(this.columnTrackHeaders[i]).width;
        maxHeaderWidth = Math.max(maxHeaderWidth, width);
      }
    }
    var xpos = Math.max(rowDendrogramWidth, maxHeaderWidth);
    var heatMapWidth = heatmapPrefSize.width;
    var maxHeatMapWidth = Math.max(50, availableWidth === -1 ? Number.MAX_VALUE : (availableWidth - rowTrackWidthSum
      - xpos
      - morpheus.HeatMap.SPACE_BETWEEN_HEAT_MAP_AND_ANNOTATIONS));
    if (maxHeatMapWidth > 0 && heatMapWidth > maxHeatMapWidth) {
      heatMapWidth = maxHeatMapWidth;
      heatMapWidth = Math.min(heatMapWidth, heatmapPrefSize.width); // can't
      // go
      // bigger
      // than
      // pref
      // width
    }
    if (this.heatmap.prefWidth !== undefined) { // heat map was manually
      // resized
      heatMapWidth = Math.min(heatmapPrefSize.width,
        this.heatmap.prefWidth);
    }
    if (this.columnDendrogram !== undefined) {
      this.columnDendrogram.setBounds({
        width: heatMapWidth,
        height: columnDendrogramHeight,
        left: xpos,
        top: 0
      });
      this.columnDendrogram.$label.css('left',
        xpos + this.columnDendrogram.getUnscaledWidth() + 10).css(
        'top', 2);
      this.columnDendrogram.$squishedLabel.css('left',
        xpos + this.columnDendrogram.getUnscaledWidth() + 10).css(
        'top', 18);

      this.beforeColumnTrackDivider.setVisible(true);
      this.beforeColumnTrackDivider.setBounds({
        left: xpos - maxHeaderWidth,
        top: ypos,
        width: maxHeaderWidth
      });
      ypos++;
    } else {
      this.beforeColumnTrackDivider.setVisible(false);
    }

    for (var i = 0, length = this.columnTracks.length; i < length; i++) {
      var track = this.columnTracks[i];
      if (track.isVisible()) {
        var size = morpheus.CanvasUtil.getPreferredSize(track);
        var headerSize = morpheus.CanvasUtil.getPreferredSize(this.columnTrackHeaders[i]);
        size.height = Math.max(size.height, headerSize.height);
        track.setBounds({
          width: heatMapWidth,
          height: size.height,
          left: xpos,
          top: ypos
        });
        this.columnTrackHeaders[i].setBounds({
          width: maxHeaderWidth,
          height: size.height,
          left: xpos - maxHeaderWidth,
          top: ypos
        });
        ypos += size.height;
      }
    }
    this.$whitespace[0].style.left = Math.ceil(xpos + heatMapWidth + 10) + 'px';
    this.$whitespace[0].style.top = '0px';
    ypos += morpheus.HeatMap.SPACE_BETWEEN_HEAT_MAP_AND_ANNOTATIONS;
    var heatMapHeight = heatmapPrefSize.height;
    if (availableHeight !== -1 && heatMapHeight > (availableHeight - ypos)) {
      heatMapHeight = Math.max(100, Math.min(heatmapPrefSize.height,
        availableHeight - ypos));
    }
    if (ypos < 0) {
      ypos = 0;
    }
    if (this.rowDendrogram) {
      this.rowDendrogram.setBounds({
        width: Math.max(rowDendrogramWidth, maxHeaderWidth),
        height: heatMapHeight,
        left: 0,
        top: ypos
      });
      this.rowDendrogram.$label.css('left', 0).css('top', 2);
      this.afterRowDendrogramDivider.setVisible(true);
      this.afterRowDendrogramDivider.setBounds({
        height: heatMapHeight,
        left: this.rowDendrogram.getUnscaledWidth(),
        top: ypos
      });
      xpos++;
    } else {
      this.afterRowDendrogramDivider.setVisible(false);
    }
    this.heatmap.setBounds({
      width: heatMapWidth,
      height: heatMapHeight,
      left: xpos,
      top: ypos
    });
    this.hSortByValuesIndicator.setBounds({
      height: 4,
      width: heatMapWidth,
      left: xpos,
      top: ypos - 4
    });
    this.hscroll.setVisible(heatMapWidth < heatmapPrefSize.width);
    this.hscroll.setExtent(heatMapWidth, heatmapPrefSize.width,
      options.scrollLeft !== undefined ? options.scrollLeft
        : (heatmapPrefSize.width === this.hscroll.getTotalExtent() ? this.hscroll.getValue()
        : heatmapPrefSize.width
        * this.hscroll.getValue()
        / this.hscroll.getMaxValue()));
    this.hscroll.setBounds({
      left: xpos,
      top: ypos + heatMapHeight + 2
    });
    xpos += heatMapWidth;
    var nvisibleRowTracks = 0;
    for (var i = 0, length = this.rowTracks.length; i < length; i++) {
      var track = this.rowTracks[i];
      if (track.isVisible()) {
        nvisibleRowTracks++;
        break;
      }
    }
    this.vSortByValuesIndicator.setBounds({
      width: 4,
      height: heatMapHeight,
      left: xpos,
      top: ypos
    });
    if (nvisibleRowTracks > 0) {
      xpos = xpos
        + morpheus.HeatMap.SPACE_BETWEEN_HEAT_MAP_AND_ANNOTATIONS; // leave
      // space
      // after
      // afterVerticalScrollBarDivider
    }
    var rowAnnotationXStart = xpos;
    // set row track bounds
    for (var i = 0, length = this.rowTracks.length; i < length; i++) {
      var track = this.rowTracks[i];
      if (track.isVisible()) {
        var size = morpheus.CanvasUtil.getPreferredSize(track);
        var headerSize = morpheus.CanvasUtil.getPreferredSize(this.rowTrackHeaders[i]);
        size.width = Math.max(headerSize.width, size.width);
        size.height = heatMapHeight;
        track.setBounds({
          width: size.width,
          height: size.height,
          left: xpos,
          top: ypos
        });

        this.rowTrackHeaders[i].setBounds({
          width: size.width,
          left: xpos,
          top: ypos - headerSize.height - 5,
          height: headerSize.height
        });
        xpos += size.width;
      }
    }
    this.afterVerticalScrollBarDivider.setVisible(nvisibleRowTracks > 0 ? true : false);
    this.afterVerticalScrollBarDivider.setBounds({
      left: rowAnnotationXStart - 2,
      top: ypos - 18
    });
    this.vscroll.setVisible(heatMapHeight < heatmapPrefSize.height);
    this.vscroll.setExtent(heatMapHeight, heatmapPrefSize.height,
      options.scrollTop !== undefined ? options.scrollTop
        : (heatmapPrefSize.height === this.vscroll.getTotalExtent() ? this.vscroll.getValue()
        : heatmapPrefSize.height
        * this.vscroll.getValue()
        / this.vscroll.getMaxValue()));
    xpos += 2;
    this.vscroll.setBounds({
      left: xpos,
      top: ypos
    });
    xpos += this.vscroll.getUnscaledWidth();
    if (this.hscroll.isVisible()) {
      ypos += this.hscroll.getUnscaledHeight() + 2;
    }
    var totalHeight = 2 + ypos + heatMapHeight;
    if (options.paint) {
      this.paintAll({
        paintRows: true,
        paintColumns: true,
        invalidateRows: true,
        invalidateColumns: true
      });
    }
    this.$parent.css({
      height: Math.ceil(totalHeight) + 'px',
      width: availableWidth === -1 ? (Math.ceil(xpos + 2) + 'px') : ''
    });

    this.updatingScroll = false;
    this.trigger('change', {
      name: 'revalidate',
      source: this,
      arguments: arguments
    });
  }
979941
function () {
                var el = document.createElement( 'canvas' ),
                    _canvas = !!( el.getContext && el.getContext( '2d' ) );
    
                this.supportCanvas = function () { return _canvas; };
                return this.supportCanvas();
            }
24147
function drawLinearMinorTicks(context, options) {
    let [hasLeft, hasRight] = drawings.prepareTicks(options);
    let ticks = [];
    let i = options.minValue;
    let minTicks = Math.abs(options.minorTicks) || 0;
    let valuePerNonExactTick = minTicks ?
        (options.maxValue - options.minValue) /
        (minTicks * (options.majorTicks.length - 1)) : 0;

    if (minTicks) {
        if (options.exactTicks) {
            let delta = BaseGauge.mod(options.majorTicks[0], minTicks) || 0;

            for (; i < options.maxValue; i += minTicks) {
                if ((delta+i) < options.maxValue) {
                    ticks.push(delta + i);
                }
            }
        }

        else {
            for (; i < options.maxValue; i += valuePerNonExactTick) {
                ticks.push(i);
            }
        }
    }

    drawLinearTicks(context,
        options.colorMinorTicks || options.colorStrokeTicks,
        ticks, options.minValue, options.maxValue,
        hasLeft, hasRight, 1, options.ticksWidthMinor / 100);
}
208015
function drawRadialPlate(context, options) {
    let pxRatio = SmartCanvas.pixelRatio;
    let d0 = options.borderShadowWidth * pxRatio;
    let r0 = context.max - d0 - (options.borderOuterWidth * pxRatio) / 2;
    let r1 = r0 - (options.borderOuterWidth * pxRatio) / 2 -
        (options.borderMiddleWidth * pxRatio) / 2 + 0.5;
    let r2 = r1 - (options.borderMiddleWidth * pxRatio) / 2 -
        (options.borderInnerWidth * pxRatio) / 2 + 0.5;
    let r3 = maxRadialRadius(context, options);
    let grad;
    let shadowDrawn = false;

    context.save();

    if (options.borderOuterWidth) {
        shadowDrawn = drawings.drawShadow(context, options, shadowDrawn);
        drawRadialBorder(r0,
            options.borderOuterWidth * pxRatio,
            context,
            options.colorBorderOuter,
            options.colorBorderOuterEnd);
    }

    if (options.borderMiddleWidth) {
        shadowDrawn = drawings.drawShadow(context, options, shadowDrawn);
        drawRadialBorder(r1,
            options.borderMiddleWidth * pxRatio,
            context,
            options.colorBorderMiddle,
            options.colorBorderMiddleEnd);
    }

    if (options.borderInnerWidth) {
        shadowDrawn = drawings.drawShadow(context, options, shadowDrawn);
        drawRadialBorder(r2,
            options.borderInnerWidth * pxRatio,
            context,
            options.colorBorderInner,
            options.colorBorderInnerEnd);
    }

    drawings.drawShadow(context, options, shadowDrawn);

    context.beginPath();
    //noinspection JSUnresolvedFunction
    context.arc(0, 0, abs(r3), 0, PI * 2, true);

    if (options.colorPlateEnd) {
        grad = context.createRadialGradient(0, 0, r3 / 2, 0, 0, r3);
        grad.addColorStop(0, options.colorPlate);
        grad.addColorStop(1, options.colorPlateEnd);
    }

    else  {
        grad = options.colorPlate;
    }

    context.fillStyle = grad;

    context.fill();
    context.closePath();

    context.restore();
}
752793
function Line(options) {

    var self = this;
    this.manager = options.manager;
    this.paper = options.paper;

    if (options.id) {
        this._id = options.id;
    } else {
        this._id = this.manager.getRandomId();
    }
    this._x1 = options.x1;
    this._y1 = options.y1;
    this._x2 = options.x2;
    this._y2 = options.y2;
    this._strokeColor = options.strokeColor;
    this._strokeWidth = options.strokeWidth || 2;
    this.handle_wh = 6;
    this._selected = false;
    this._zoomFraction = 1;
    if (options.zoom) {
        this._zoomFraction = options.zoom / 100;
    }

    this.element = this.paper.path();
    this.element.attr({'cursor': 'pointer'});

    // Drag handling of line
    if (this.manager.canEdit) {
        this.element.drag(
            function(dx, dy) {
                // DRAG, update location and redraw
                dx = dx / self._zoomFraction;
                dy = dy / self._zoomFraction;

                var offsetX = dx - this.prevX;
                var offsetY = dy - this.prevY;
                this.prevX = dx;
                this.prevY = dy;

                // Manager handles move and redraw
                self.manager.moveSelectedShapes(offsetX, offsetY, true);
                return false;
            },
            function() {
                // START drag: note the location of all points
                self._handleMousedown();
                this.prevX = 0;
                this.prevY = 0;
                return false;
            },
            function() {
                // STOP
                // notify manager if line has moved
                if (this.prevX !== 0 || this.prevY !== 0) {
                    self.manager.notifySelectedShapesChanged();
                }
                return false;
            }
        );
    }

    this.createHandles();

    this.drawShape();
}
283555
def draw(svg, coords, options={})
      # svg.polygon wants a long string of coords. 
      points_value = "0,#{height} #{stringify_coords(coords).join(' ')} #{width},#{height}"

      # Experimental, for later user.
      # This was supposed to add some fun filters, 3d effects and whatnot.
      # Neither ImageMagick nor Mozilla SVG render this well (at all).  Maybe a future thing.
      #
      # svg.defs {
      #   svg.filter(:id => 'MyFilter', :filterUnits => 'userSpaceOnUse', :x => 0, :y => 0, :width => 200, :height => '120') {
      #     svg.feGaussianBlur(:in => 'SourceAlpha', :stdDeviation => 4, :result => 'blur')
      #     svg.feOffset(:in => 'blur', :dx => 4, :dy => 4, :result => 'offsetBlur')
      #     svg.feSpecularLighting( :in => 'blur', :surfaceScale => 5, :specularConstant => '.75',
      #                             :specularExponent => 20, 'lighting-color' => '#bbbbbb',
      #                             :result => 'specOut') {
      #       svg.fePointLight(:x => '-5000', :y => '-10000', :z => '20000')
      #     }
      #     
      #     svg.feComposite(:in => 'specOut', :in2 => 'SourceAlpha', :operator => 'in', :result => 'specOut')
      #     svg.feComposite(:in => 'sourceGraphic', :in2 => 'specOut', :operator => 'arithmetic',
      #                     :k1 => 0, :k2 => 1, :k3 => 1, :k4 => 0, :result => 'litPaint')
      #                     
      #     svg.feMerge {
      #       svg.feMergeNode(:in => 'offsetBlur')
      #       svg.feMergeNode(:in => 'litPaint')
      #     }
      #   }
      # }
      svg.g(:transform => "translate(0, -#{relative(2)})") {
        svg.polygon(:points => points_value, :style => "fill: black; stroke: black; fill-opacity: 0.06; stroke-opacity: 0.06;")
      }

      svg.polygon(:points => points_value, :fill => color.to_s, :stroke => color.to_s, 'style' => "opacity: #{opacity}")
    end
117764
function parseOptions (options) {
  return {
    [ELEMENT_TYPE.NORMAL]: (options && options.html && options.html.normal) || 'always',
    [ELEMENT_TYPE.VOID]: (options && options.html && options.html.void) || 'never',
    [ELEMENT_TYPE.COMPONENT]: (options && options.html && options.html.component) || 'always',
    [ELEMENT_TYPE.SVG]: (options && options.svg) || 'always',
    [ELEMENT_TYPE.MATH]: (options && options.math) || 'always'
  }
}
716287
function Ellipse(options) {

    var self = this;
    this.manager = options.manager;
    this.paper = options.paper;

    if (options.id) {
        this._id = options.id;
    } else {
        this._id = this.manager.getRandomId();
    }
    this._x = options.x;
    this._y = options.y;
    this._radiusX = options.radiusX;
    this._radiusY = options.radiusY;
    this._rotation = options.rotation || 0;

    // We handle transform matrix by creating this.Matrix
    // This is used as a one-off transform of the handles positions
    // when they are created. This then updates the _x, _y, _radiusX, _radiusY & rotation
    // of the ellipse itself (see below)
    if (options.transform && options.transform.startsWith('matrix')) {
        var tt = options.transform.replace('matrix(', '').replace(')', '').split(" ");
        var a1 = parseFloat(tt[0]);
        var a2 = parseFloat(tt[1]);
        var b1 = parseFloat(tt[2]);
        var b2 = parseFloat(tt[3]);
        var c1 = parseFloat(tt[4]);
        var c2 = parseFloat(tt[5]);
        this.Matrix = Raphael.matrix(a1, a2, b1, b2, c1, c2);
    }

    if (this._radiusX === 0 || this._radiusY === 0) {
        this._yxRatio = 0.5;
    } else {
        this._yxRatio = this._radiusY / this._radiusX;
    }

    this._strokeColor = options.strokeColor;
    this._strokeWidth = options.strokeWidth || 2;
    this._selected = false;
    this._zoomFraction = 1;
    if (options.zoom) {
        this._zoomFraction = options.zoom / 100;
    }
    this.handle_wh = 6;

    this.element = this.paper.ellipse();
    this.element.attr({'fill-opacity': 0.01,
                        'fill': '#fff',
                        'cursor': 'pointer'});

    // Drag handling of ellipse
    if (this.manager.canEdit) {
        this.element.drag(
            function(dx, dy) {
                // DRAG, update location and redraw
                dx = dx / self._zoomFraction;
                dy = dy / self._zoomFraction;

                var offsetX = dx - this.prevX;
                var offsetY = dy - this.prevY;
                this.prevX = dx;
                this.prevY = dy;

                // Manager handles move and redraw
                self.manager.moveSelectedShapes(offsetX, offsetY, true);
                return false;
            },
            function() {
                // START drag: note the start location
                self._handleMousedown();
                this.prevX = 0;
                this.prevY = 0;
                return false;
            },
            function() {
                // STOP
                // notify changed if moved
                if (this.prevX !== 0 || this.prevY !== 0) {
                    self.manager.notifySelectedShapesChanged();
                }
                return false;
            }
        );
    }

    // create handles, applying this.Matrix if set
    this.createHandles();
    // update x, y, radiusX, radiusY & rotation
    // If we have Matrix, recalculate width/height ratio based on all handles
    var resizeWidth = !!this.Matrix;
    this.updateShapeFromHandles(resizeWidth);
    // and draw the Ellipse
    this.drawShape();
}