- createClipDiv({x:plotArea.x, y:plotArea.y+plotArea.h, w:this.width-plotArea.x, h:this.height-plotArea.h-plotArea.y});
-}
-
-DygraphCanvasRenderer.prototype._renderAxis = function() {
- if (!this.attr_('drawXAxis') && !this.attr_('drawYAxis')) return;
-
- // Round pixels to half-integer boundaries for crisper drawing.
- function halfUp(x){return Math.round(x)+0.5};
- function halfDown(y){return Math.round(y)-0.5};
-
- var context = this.elementContext;
-
- var labelStyle = {
- position: "absolute",
- fontSize: this.attr_('axisLabelFontSize') + "px",
- zIndex: 10,
- color: this.attr_('axisLabelColor'),
- width: this.attr_('axisLabelWidth') + "px",
- // height: this.attr_('axisLabelFontSize') + 2 + "px",
- lineHeight: "normal", // Something other than "normal" line-height screws up label positioning.
- overflow: "hidden"
- };
- var makeDiv = function(txt, axis, prec_axis) {
- var div = document.createElement("div");
- for (var name in labelStyle) {
- if (labelStyle.hasOwnProperty(name)) {
- div.style[name] = labelStyle[name];
+ createClipDiv({
+ x: plotArea.x,
+ y: plotArea.y + plotArea.h,
+ w: this.width - plotArea.x,
+ h: this.height - plotArea.h - plotArea.y
+ });
+};
+
+
+/**
+ * Returns a predicate to be used with an iterator, which will
+ * iterate over points appropriately, depending on whether
+ * connectSeparatedPoints is true. When it's false, the predicate will
+ * skip over points with missing yVals.
+ */
+DygraphCanvasRenderer._getIteratorPredicate = function(connectSeparatedPoints) {
+ return connectSeparatedPoints ?
+ DygraphCanvasRenderer._predicateThatSkipsEmptyPoints :
+ null;
+};
+
+DygraphCanvasRenderer._predicateThatSkipsEmptyPoints =
+ function(array, idx) {
+ return array[idx].yval !== null;
+};
+
+/**
+ * Draws a line with the styles passed in and calls all the drawPointCallbacks.
+ * @param {Object} e The dictionary passed to the plotter function.
+ * @private
+ */
+DygraphCanvasRenderer._drawStyledLine = function(e,
+ color, strokeWidth, strokePattern, drawPoints,
+ drawPointCallback, pointSize) {
+ var g = e.dygraph;
+ // TODO(konigsberg): Compute attributes outside this method call.
+ var stepPlot = g.getOption("stepPlot", e.setName);
+
+ if (!Dygraph.isArrayLike(strokePattern)) {
+ strokePattern = null;
+ }
+
+ var drawGapPoints = g.getOption('drawGapEdgePoints', e.setName);
+
+ var points = e.points;
+ var iter = Dygraph.createIterator(points, 0, points.length,
+ DygraphCanvasRenderer._getIteratorPredicate(
+ g.getOption("connectSeparatedPoints"))); // TODO(danvk): per-series?
+
+ var stroking = strokePattern && (strokePattern.length >= 2);
+
+ var ctx = e.drawingContext;
+ ctx.save();
+ if (stroking) {
+ ctx.installPattern(strokePattern);
+ }
+
+ var pointsOnLine = DygraphCanvasRenderer._drawSeries(
+ e, iter, strokeWidth, pointSize, drawPoints, drawGapPoints, stepPlot, color);
+ DygraphCanvasRenderer._drawPointsOnLine(
+ e, pointsOnLine, drawPointCallback, color, pointSize);
+
+ if (stroking) {
+ ctx.uninstallPattern();
+ }
+
+ ctx.restore();
+};
+
+/**
+ * This does the actual drawing of lines on the canvas, for just one series.
+ * Returns a list of [canvasx, canvasy] pairs for points for which a
+ * drawPointCallback should be fired. These include isolated points, or all
+ * points if drawPoints=true.
+ * @param {Object} e The dictionary passed to the plotter function.
+ * @private
+ */
+DygraphCanvasRenderer._drawSeries = function(e,
+ iter, strokeWidth, pointSize, drawPoints, drawGapPoints, stepPlot, color) {
+
+ var prevCanvasX = null;
+ var prevCanvasY = null;
+ var nextCanvasY = null;
+ var isIsolated; // true if this point is isolated (no line segments)
+ var point; // the point being processed in the while loop
+ var pointsOnLine = []; // Array of [canvasx, canvasy] pairs.
+ var first = true; // the first cycle through the while loop
+
+ var ctx = e.drawingContext;
+ ctx.beginPath();
+ ctx.strokeStyle = color;
+ ctx.lineWidth = strokeWidth;
+
+ // NOTE: we break the iterator's encapsulation here for about a 25% speedup.
+ var arr = iter.array_;
+ var limit = iter.end_;
+ var predicate = iter.predicate_;
+
+ for (var i = iter.start_; i < limit; i++) {
+ point = arr[i];
+ if (predicate) {
+ while (i < limit && !predicate(arr, i)) {
+ i++;