=== modified file 'src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.canvas_renderer.js' --- src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.canvas_renderer.js 2016-02-13 21:56:51 +0000 +++ src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.canvas_renderer.js 2016-02-15 21:28:46 +0000 @@ -498,15 +498,9 @@ * Y coordinate of the ending pixel to be drawn. * @param {Number[]} color * Array of 3 integer values between 0 and 255 inclusive, representing an RGB color. - * - * @return {Array} path - * The {x:.,y:.} point per a pixel array that represents the drawing line segment. */ CanvasRenderer.prototype.drawLineSegment = function(x1, y1, x2, y2, color) { - // holds the line pixels to draw - var path = []; - x1 = x1 + this.origin.x; x2 = x2 + this.origin.x; @@ -517,7 +511,7 @@ var d = this.cutLine(x1, y1, x2, y2); if (d === null) { - return path; + return; } x1 = d[0]; y1 = d[1]; @@ -527,60 +521,17 @@ var dx = Math.abs(x2 - x1); var dy = Math.abs(y2 - y1); - var directStroke = this.strokesManager.isDirectDrawingStrokeStyle(this.strokeStyleId); - + var strokeRenderer = this.strokesManager.getStrokePathRenderer(this, this.strokeStyleId, + this.strokeWidth, color); + strokeRenderer.beginStroke(); if (dx === 0 || dy === 0) { - var width = dx + 1; - var height = dy + 1; - - var buffer = new ArrayBuffer(4 * width * height); - - var imageData = new Uint8ClampedArray(buffer); - - var x = x1; - var y = y1; - var curr = 0; - while(x <= x2 && y <= y2) - { - if (directStroke) - { - imageData[curr++] = color[0]; - imageData[curr++] = color[1]; - imageData[curr++] = color[2]; - imageData[curr++] = 255; - } - path.push({x : x, y : y}); - if (dy === 0) - { - x = x + 1; - } - else - { - y = y + 1; - } - - } - if (directStroke) - { - this.screenCapture = this.ctx.getImageData(x1, y1, width, height); - if (p2j.isChrome) - { - copyImage(this.screenCapture, this.screenCapture.data, imageData, width, height, 0); - } - else - { - this.screenCapture.data.set(imageData, 0); - } - this.ctx.putImageData(this.screenCapture, x1, y1); - } + strokeRenderer.strokeLine(x1, y1, x2, y2); } else { - path = drawSlopedLineSegment(this, x1, y1, x2, y2, color, directStroke); + this.drawSlopedLineSegment(x1, y1, x2, y2, strokeRenderer); } - - return path; }; /** @@ -588,8 +539,6 @@ *
* This is an implementation of the well known 50+ year old Bresenham algorithm. * - * @param {CanvasRenderer} renderer - * The canvas renderer. * @param {Number} x1 * X coordinate of the starting pixel to be drawn. * @param {Number} y1 @@ -598,19 +547,11 @@ * X coordinate of the ending pixel to be drawn. * @param {Number} y2 * Y coordinate of the ending pixel to be drawn. - * @param {Number[]} color - * Array of 3 integer values between 0 and 255 inclusive, representing an RGB color. - * @param {Boolean} draw - * True indicates that the line pixels are drawn on the canvas by the renderer. - * - * @return {Array} path - * The {x:.,y:.} point per a pixel array that represents the drawing line segment. + * @param {StrokeRenderer} strokeRenderer + * The current stroke renderer. */ -function drawSlopedLineSegment(renderer, x1, y1, x2, y2, color, draw) +CanvasRenderer.prototype.drawSlopedLineSegment = function(x1, y1, x2, y2, strokeRenderer) { - // holds the line pixels to draw - var path = []; - var dx = Math.abs(x2 - x1); var dy = Math.abs(y2 - y1); @@ -628,11 +569,7 @@ while (true) { - if (draw) - { - renderer.drawPixel(x, y, color); - } - path.push({x : x, y : y}); + strokeRenderer.strokePoint(x, y); tooMany++; @@ -665,11 +602,10 @@ y += yIncr; } } - - return path; } /** + * * Draw a line in the given color from (x1, y1) to (x2, y2) inclusive, using direct drawing and * add its pixels path to the end of the provided pixels path. *
@@ -685,22 +621,14 @@ * Y coordinate of the ending pixel to be drawn. * @param {Number[]} color * Array of 3 integer values between 0 and 255 inclusive, representing an RGB color. - * @param {Array} path - * The provided holder of {x:.,y:.} points, the target drawing as a set of sequential - * line points will be added at the end of the provided path. - * @return {Array} - * The {x:.,y:.} point per a pixel array that represents the drawing line segment. */ -CanvasRenderer.prototype.drawLine = function(x1, y1, x2, y2, color, path) +CanvasRenderer.prototype.drawLine = function(x1, y1, x2, y2, color) { - var segment = this.drawLineSegment(x1, y1, x2, y2, color); - Array.prototype.push.apply(path, segment); - return segment; + this.drawLineSegment(x1, y1, x2, y2, color); } /** - * Stroke a line in the given color from (x1, y1) to (x2, y2) inclusive, using direct drawing and - * add its pixels path to the end of the provided pixels path. + * Stroke a line in the given color from (x1, y1) to (x2, y2) inclusive. *
* This is an implementation of the well known 50+ year old Bresenham algorithm.
*
@@ -714,18 +642,10 @@
* Y coordinate of the ending pixel to be drawn.
* @param {Number[]} color
* Array of 3 integer values between 0 and 255 inclusive, representing an RGB color.
- * @param {Array} path
- * The provided holder of {x:.,y:.} points, the target drawing as a set of sequential
- * line points will be added at the end of the provided path.
*/
CanvasRenderer.prototype.strokeLineSegment = function(x1, y1, x2, y2, color)
{
- var segment = this.drawLineSegment(x1, y1, x2, y2, color);
- this.strokesManager.applyStrokeToPath(this,
- this.strokeStyleId,
- this.strokeWidth,
- color,
- segment);
+ this.drawLineSegment(x1, y1, x2, y2, color);
}
/**
@@ -745,15 +665,11 @@
* This will be used for the border lines and when in fill mode, also the interior.
* @param {Boolean} fill
* true
to fill the drawn rectangle with the given color.
- *
- * @return {Array} path
- * The {x:.,y:.} point per a pixel array that represents the rectangle outerline.
*/
CanvasRenderer.prototype.drawRect = function(x, y, width, height, color, fill)
{
// filled rectangles draw 1 pixel smaller in 2 dimensions than stroked rectangles
var inset = 0;
- var path = [];
// use vector operations for the interior of the rectangle
if (fill)
{
@@ -765,12 +681,10 @@
// now overdraw the stroked portion to eliminate anti-aliasing, we draw in a
// clockwise direction (since we are not using paths, this is not strictly necessary)
- this.drawLine(x, y, x + width - inset, y, color, path);
- this.drawLine(x + width - inset, y + 1, x + width - inset, y + height - inset, color, path);
- this.drawLine(x + width - 1 - inset, y + height - inset, x + 1, y + height - inset, color, path);
- this.drawLine(x, y + height - inset, x, y + 1, color, path);// close the path
-
- return path;
+ this.drawLine(x, y, x + width - inset, y, color);
+ this.drawLine(x + width - inset, y + 1, x + width - inset, y + height - inset, color);
+ this.drawLine(x + width - 1 - inset, y + height - inset, x + 1, y + height - inset, color);
+ this.drawLine(x, y + height - inset, x, y + 1, color);// close the path
};
/**
@@ -795,7 +709,6 @@
{
// filled rectangles draw 1 pixel smaller in 2 dimensions than stroked rectangles
var inset = 0;
- var path = [];
// use vector operations for the interior of the rectangle
if (fill)
{
@@ -807,16 +720,11 @@
// now overdraw the stroked portion to eliminate anti-aliasing, we draw in a
// clockwise direction (since we are not using paths, this is not strictly necessary)
- this.drawLine(x, y, x + width - inset, y, color, path);
- this.drawLine(x + width - inset, y + 1, x + width - inset, y + height - inset, color, path);
- this.drawLine(x + width - 1 - inset, y + height - inset, x + 1, y + height - inset, color, path);
- this.drawLine(x, y + height - inset, x, y + 1, color, path);// close the path
+ this.drawLine(x, y, x + width - inset, y, color);
+ this.drawLine(x + width - inset, y + 1, x + width - inset, y + height - inset, color);
+ this.drawLine(x + width - 1 - inset, y + height - inset, x + 1, y + height - inset, color);
+ this.drawLine(x, y + height - inset, x, y + 1, color);// close the path
- this.strokesManager.applyStrokeToPath(this,
- this.strokeStyleId,
- this.strokeWidth,
- color,
- path);
};
/**
@@ -864,7 +772,7 @@
var data = img.data;
if (p2j.isChrome)
{
- copyImage(img, data, imgData, width, height, imgDataOffset);
+ this.copyImage(img, data, imgData, width, height, imgDataOffset);
}
else
{
@@ -924,7 +832,7 @@
* Returns the modified screen image data array with the target image.
*
*/
-function copyImage(img, data, imgData, width, height, imgDataOffset)
+CanvasRenderer.prototype.copyImage = function(img, data, imgData, width, height, imgDataOffset)
{
var awidth = img.width;
var aheight = img.height;
@@ -1037,16 +945,10 @@
this.renderClosedPath(fill);
// overdraw the anti-aliased line segments
- var path = [];
- this.drawLine(topLeftX, topLeftY, topRightX, topRightY, color, path);
- this.drawLine(rightUpX, rightUpY, rightDownX, rightDownY, color, path);
- this.drawLine(bottomLeftX, bottomLeftY, bottomRightX, bottomRightY, color, path);
- this.drawLine(leftUpX, leftUpY, leftDownX, leftDownY, color, path);
- this.strokesManager.applyStrokeToPath(this,
- this.strokeStyleId,
- this.strokeWidth,
- color,
- path);
+ this.drawLine(topLeftX, topLeftY, topRightX, topRightY, color);
+ this.drawLine(rightUpX, rightUpY, rightDownX, rightDownY, color);
+ this.drawLine(bottomLeftX, bottomLeftY, bottomRightX, bottomRightY, color);
+ this.drawLine(leftUpX, leftUpY, leftDownX, leftDownY, color);
};
/**
@@ -1115,26 +1017,14 @@
// draw the top and left sides in the contrasting color (raised mode) or the darker color
// otherwise
- var path = [];// create new pixels path to draw
- this.drawLine(x, y, x + width - 2 - inset, y, current, path);
- this.drawLine(x, y + 1, x, y + height - 1 - inset, current, path);
- this.strokesManager.applyStrokeToPath(this,
- this.strokeStyleId,
- this.strokeWidth,
- current,
- path);
+ this.drawLine(x, y, x + width - 2 - inset, y, current);
+ this.drawLine(x, y + 1, x, y + height - 1 - inset, current);
// draw the bottom and right sides in the darker color (raised mode) or the contrasting
// color otherwise
current = raised ? darker : lighter;
- path = []; // create new pixels path to draw
- this.drawLine(x + 1, y + height - 1 - inset, x + width - 1 - inset, y + height - 1 - inset, current, path);
- this.drawLine(x + width - 1 - inset, y, x + width - 1 - inset, y + height - 2, current, path);
- this.strokesManager.applyStrokeToPath(this,
- this.strokeStyleId,
- this.strokeWidth,
- current,
- path);
+ this.drawLine(x + 1, y + height - 1 - inset, x + width - 1 - inset, y + height - 1 - inset, current);
+ this.drawLine(x + width - 1 - inset, y, x + width - 1 - inset, y + height - 2, current);
// clear the clipping region
this.ctx.restore();
@@ -1158,8 +1048,6 @@
* @param {Boolean} fill
* true
to fill the rectangle with the current color, otherwise just
* stroke the rectangle.
- * @return {Array}
- * The {x:.,y:.} point per a pixel array that represents this poligon.
*/
CanvasRenderer.prototype.drawPolygon = function(xPoints, yPoints, num, color, fill)
{
@@ -1177,15 +1065,13 @@
this.ctx.closePath();
this.renderClosedPath(fill);
}
- var path = [];
// now overdraw the stroked portion
for (i = 0; i < (num - 1); i++)
{
- this.drawLine(xPoints[i], yPoints[i], xPoints[i + 1], yPoints[i + 1], color, path);
+ this.drawLine(xPoints[i], yPoints[i], xPoints[i + 1], yPoints[i + 1], color);
}
// close the path
- this.drawLine(xPoints[num - 1], yPoints[num - 1], xPoints[0], yPoints[0], color, path);
- return path;
+ this.drawLine(xPoints[num - 1], yPoints[num - 1], xPoints[0], yPoints[0], color);
};
/**
@@ -1205,12 +1091,7 @@
*/
CanvasRenderer.prototype.strokePolygon = function(xPoints, yPoints, num, color, fill)
{
- var path = this.drawPolygon(xPoints, yPoints, num, color, fill);
- this.strokesManager.applyStrokeToPath(this,
- this.strokeStyleId,
- this.strokeWidth,
- color,
- path);
+ this.drawPolygon(xPoints, yPoints, num, color, fill);
};
/**
@@ -1721,7 +1602,7 @@
var y1 = origY;
var y2 = y1;
- this.strokeLineSegment(this.ctx, x1, y1, x2, y2, this.rawColor);
+ this.strokeLineSegment(x1, y1, x2, y2, this.rawColor);
}
}
=== modified file 'src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.strokes.js'
--- src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.strokes.js 2015-10-22 23:14:19 +0000
+++ src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.strokes.js 2016-02-15 21:29:10 +0000
@@ -11,6 +11,7 @@
** -#- -I- --Date-- ------------------------------Description----------------------------------
** 001 SBI 20150819 The first version defines LineStrokes class as a strokes manager.
** 002 SBI 20151012 Added XOR processing and dotted large line stroke support.
+** 003 SBI 20160215 Reduced putImageData invocations for horizontal and vertical lines.
*/
"use strict";
@@ -193,7 +194,7 @@
*
* @return The stroke path renderer.
*/
- function getStrokePathRenderer(canvasRenderer, strokeStyle, width, strokeColor)
+ this.getStrokePathRenderer = function(canvasRenderer, strokeStyle, width, strokeColor)
{
var basicStroke = getLineStroke(strokeStyle, width);
@@ -207,7 +208,7 @@
case LineStrokeEnum.DOTTED_LARGE:
return new DotsPathRenderer(canvasRenderer, basicStroke, strokeColor);
default:
- return { applyStroke : function (path) {} };
+ return new DefaultPathRenderer(canvasRenderer, strokeColor);
}
};
@@ -244,40 +245,8 @@
context.lineDashOffset = basicStroke.getDashPhase();
}
}
-
- /**
- * Apply the given stroke style to the area outer bounds.
- *
- * @param {CanvasRenderer} canvasRenderer
- * The canvas renderer.
- * @param {Number} strokeStyle
- * The stroke style id.
- * @param {Number} width
- * The line width.
- * @param {Number[]} strokeColor
- * The array of 3 integer values between 0 and 255 inclusive, representing
- * a stroke color.
- * @param {Array} path
- * The array of points that forms the outline of the target area.
- */
- this.applyStrokeToPath = function(canvasRenderer, strokeStyle, width, strokeColor, path)
- {
- var renderer = getStrokePathRenderer(canvasRenderer, strokeStyle, width, strokeColor);
- renderer.applyStroke(path);
- }
/**
- * Returns true if for the given stroke style it is supposed to draw lines and rectangles
- * using drawing functions without any corrections of their results, otherwise, false.
- *
- * @return {boolean} true or false
- */
- this.isDirectDrawingStrokeStyle = function(strokeStyle)
- {
- return LineStrokeEnum.DEFAULT == strokeStyle;
- }
-
- /**
* Returns the default stroke that is a solid line style with 1 pixel line width.
*
* @return {Number} The default stroke style.
@@ -288,6 +257,53 @@
}
/**
+ * Defines StrokeRenderer class
+ */
+ function StrokeRenderer()
+ {
+ }
+
+ /**
+ * Defines the constructor function
+ */
+ StrokeRenderer.prototype.constructor = StrokeRenderer;
+
+ /**
+ * Prepare the object.
+ */
+ StrokeRenderer.prototype.beginStroke = function()
+ {
+ };
+
+ /**
+ * Apply the stroke to lines given by the absolute coordinates.
+ *
+ * @param {Number} x1
+ * X coordinate of the starting pixel to be drawn.
+ * @param {Number} y1
+ * Y coordinate of the starting pixel to be drawn.
+ * @param {Number} x2
+ * X coordinate of the ending pixel to be drawn.
+ * @param {Number} y2
+ * Y coordinate of the ending pixel to be drawn.
+ */
+ StrokeRenderer.prototype.strokeLine = function(x1, y1, x2, y2)
+ {
+ };
+
+ /**
+ * Apply the stroke to the next point given by its coordinates (x, y).
+ *
+ * @param {Number} x
+ * X coordinate of the point to be drawn.
+ * @param {Number} y
+ * Y coordinate of the point to be drawn.
+ */
+ StrokeRenderer.prototype.strokePoint = function(x, y)
+ {
+ };
+
+ /**
* Used to draw dash patterns on lines of pixels.
*
* @param {CanvasRenderer} canvasRenderer
@@ -303,6 +319,7 @@
var pixel = canvasRenderer.createImageData(1, 1);
var pixelData = pixel.data;
pixelData[3] = 0xFF;
+ var state = {};
/**
* Normalizes a dash offset distance according to the given dash pattern.
@@ -339,12 +356,9 @@
}
/**
- * Apply the given stroke to the line of pixels called a path.
- *
- * @param {Array} path
- * The array of points that forms the outline of the target area.
+ * Prepares the given stroke to be applied to the line of pixels called a path.
*/
- this.applyStroke = function (path)
+ this.beginStroke = function()
{
var dash = basicStroke.getDash();
if (!dash || dash.length == 0)
@@ -361,28 +375,119 @@
var idx = patternObj.startIdx;
var rest = dash[idx] - phase;
- for (var i = 0; i < path.length; i++)
+ state.dash = dash;
+ state.len = len;
+ state.dashOn = dashOn;
+ state.idx = idx;
+ state.rest = rest;
+ }
+
+ /**
+ * Apply the stroke to vertical or horizontal lines given by the absolute coordinates that
+ * satisfy x1 <= x2 and y1 <= y2.
+ *
+ * @param {Number} x1
+ * X coordinate of the starting pixel to be drawn.
+ * @param {Number} y1
+ * Y coordinate of the starting pixel to be drawn.
+ * @param {Number} x2
+ * X coordinate of the ending pixel to be drawn.
+ * @param {Number} y2
+ * Y coordinate of the ending pixel to be drawn.
+ */
+ this.strokeLine = function(x1, y1, x2, y2)
+ {
+ var rest = state.rest;
+ var idx = state.idx;
+ var len = state.len;
+ var dashOn = state.dashOn;
+ var dash = state.dash;
+
+ var width = x2 - x1 + 1;
+ var height = y2 - y1 + 1;
+ var screenCapture = canvasRenderer.ctx.getImageData(x1, y1, width, height);
+ var data = screenCapture.data;
+ var length = 4 * width * height;
+ var buffer = new ArrayBuffer(length);
+ var imageData = new Uint8ClampedArray(buffer);
+ var i = 0;
+ while(i < length)
{
- var point = path[i];
if (rest < 1)
{
- idx = (idx + 1) % len;
- rest = dash[idx];
+ idx = (idx + 1) % len;
+ rest = state.dash[idx];
dashOn = !dashOn;
}
rest -= 1;
-
+
if (dashOn)
{
- pixelData[0] = strokeColor[0];
- pixelData[1] = strokeColor[1];
- pixelData[2] = strokeColor[2];
- canvasRenderer.putImageData(pixel, point.x, point.y);
- }
- }
+ imageData[i++] = strokeColor[0];
+ imageData[i++] = strokeColor[1];
+ imageData[i++] = strokeColor[2];
+ imageData[i++] = 255;
+ }
+ else
+ {
+ imageData[i++] = 0;
+ imageData[i++] = 0;
+ imageData[i++] = 0;
+ imageData[i++] = 0;
+ }
+ }
+ canvasRenderer.copyImage(screenCapture, data, imageData, width, height, 0);
+ canvasRenderer.putImageData(screenCapture, x1, y1);
+ state.dashOn = dashOn;
+ state.rest = rest;
+ state.idx = idx;
+ }
+
+ /**
+ * Apply the stroke to the next point given by its coordinates (x, y).
+ *
+ * @param {Number} x
+ * X coordinate of the point to be drawn.
+ * @param {Number} y
+ * Y coordinate of the point to be drawn.
+ */
+ this.strokePoint = function(x, y)
+ {
+ var rest = state.rest;
+ var idx = state.idx;
+ var len = state.len;
+ var dashOn = state.dashOn;
+ if (rest < 1)
+ {
+ idx = (idx + 1) % len;
+ rest = state.dash[idx];
+ dashOn = !dashOn;
+ }
+ rest -= 1;
+ if (dashOn)
+ {
+ pixelData[0] = strokeColor[0];
+ pixelData[1] = strokeColor[1];
+ pixelData[2] = strokeColor[2];
+ canvasRenderer.putImageData(pixel, x, y);
+ }
+
+ state.dashOn = dashOn;
+ state.rest = rest;
+ state.idx = idx;
+ }
+
+ }
+
+ /**
+ * DotsPathRenderer implements StrokeRenderer methods
+ */
+ DotsPathRenderer.prototype = Object.create(StrokeRenderer.prototype);
- }
- }
+ /**
+ * Defines the constructor function
+ */
+ DotsPathRenderer.prototype.constructor = DotsPathRenderer;
/**
* Used to widen lines of pixels.
@@ -408,20 +513,176 @@
imageData[i + 2] = strokeColor[2];
imageData[i + 3] = 0xFF;
}
-
- /**
- * To widen the line of pixels called a path according to the stroke style.
- *
- * @param {Array} path
- * The array of points that forms the outline of the target area.
- */
- this.applyStroke = function (path)
- {
- for (var i = 0; i < path.length; i++)
- {
- var point = path[i];
- canvasRenderer.putImageData(image, point.x - (width >> 1), point.y - (width >> 1));
- }
- }
- }
-}
\ No newline at end of file
+
+ /**
+ * Prepares the given stroke to be applied to the line of pixels called a path.
+ */
+ this.beginStroke = function()
+ {
+ }
+
+ /**
+ * Apply the stroke to vertical or horizontal lines given by the absolute coordinates that
+ * satisfy x1 <= x2 and y1 <= y2.
+ *
+ * @param {Number} x1
+ * X coordinate of the starting pixel to be drawn.
+ * @param {Number} y1
+ * Y coordinate of the starting pixel to be drawn.
+ * @param {Number} x2
+ * X coordinate of the ending pixel to be drawn.
+ * @param {Number} y2
+ * Y coordinate of the ending pixel to be drawn.
+ */
+ this.strokeLine = function(x1, y1, x2, y2)
+ {
+ var lineWidth = x2 - x1 + width;
+ var lineHeight = y2 - y1 + width;
+ var x0 = x1 - (width >> 1);
+ var y0 = y1 - (width >> 1);
+ var screenCapture = canvasRenderer.ctx.getImageData(x0, y0, lineWidth, lineHeight);
+ var data = screenCapture.data;
+ var length = 4 * lineWidth * lineHeight;
+
+ var imageBuffer = new ArrayBuffer(length);
+ var imageBufferView = new Uint8ClampedArray(imageBuffer);
+ for (var i = 0; i < length; i += 4)
+ {
+ imageBufferView[i] = strokeColor[0];
+ imageBufferView[i + 1] = strokeColor[1];
+ imageBufferView[i + 2] = strokeColor[2];
+ imageBufferView[i + 3] = 255;
+ }
+ if (p2j.isChrome)
+ {
+ canvasRenderer.copyImage(screenCapture, data, imageBufferView, lineWidth, lineHeight, 0);
+ }
+ else
+ {
+ data.set(imageBufferView, 0);
+ }
+ canvasRenderer.putImageData(screenCapture, x0, y0);
+ }
+
+ /**
+ * Apply the stroke to the next point given by its coordinates (x, y).
+ *
+ * @param {Number} x
+ * X coordinate of the point to be drawn.
+ * @param {Number} y
+ * Y coordinate of the point to be drawn.
+ */
+ this.strokePoint = function(x, y)
+ {
+ canvasRenderer.putImageData(image, x - (width >> 1), y - (width >> 1));
+ }
+
+ }
+
+ /**
+ * WidenPathRenderer implements StrokeRenderer methods
+ */
+ WidenPathRenderer.prototype = Object.create(StrokeRenderer.prototype);
+
+ /**
+ * Defines the constructor function
+ */
+ WidenPathRenderer.prototype.constructor = WidenPathRenderer;
+
+ /**
+ * The default lines renderer.
+ *
+ * @param {CanvasRenderer} canvasRenderer
+ * The canvas renderer.
+ * @param {Number[]} strokeColor
+ * The array of 3 integer values between 0 and 255 inclusive, representing
+ * a stroke color.
+ */
+ function DefaultPathRenderer(canvasRenderer, strokeColor)
+ {
+ var width = defaultStroke.getWidth();
+ var image = canvasRenderer.createImageData(width, width);
+ var imageData = image.data;
+
+ for (var i = 0; i < 4 * width * width; i += 4)
+ {
+ imageData[i] = strokeColor[0];
+ imageData[i + 1] = strokeColor[1];
+ imageData[i + 2] = strokeColor[2];
+ imageData[i + 3] = 255;
+ }
+
+ /**
+ * Prepares the given stroke to be applied to the line of pixels called a path.
+ */
+ this.beginStroke = function()
+ {
+ }
+
+ /**
+ * Apply the stroke to vertical or horizontal lines given by the absolute coordinates that
+ * satisfy x1 <= x2 and y1 <= y2.
+ *
+ * @param {Number} x1
+ * X coordinate of the starting pixel to be drawn.
+ * @param {Number} y1
+ * Y coordinate of the starting pixel to be drawn.
+ * @param {Number} x2
+ * X coordinate of the ending pixel to be drawn.
+ * @param {Number} y2
+ * Y coordinate of the ending pixel to be drawn.
+ */
+ this.strokeLine = function(x1, y1, x2, y2)
+ {
+ var lineWidth = x2 - x1 + 1;
+ var lineHeight = y2 - y1 + 1;
+ var screenCapture = canvasRenderer.ctx.getImageData(x1, y1, lineWidth, lineHeight);
+ var data = screenCapture.data;
+ var length = 4 * lineWidth * lineHeight;
+
+ var imageBuffer = new ArrayBuffer(length);
+ var imageBufferView = new Uint8ClampedArray(imageBuffer);
+ for (var i = 0; i < length; i += 4)
+ {
+ imageBufferView[i] = strokeColor[0];
+ imageBufferView[i + 1] = strokeColor[1];
+ imageBufferView[i + 2] = strokeColor[2];
+ imageBufferView[i + 3] = 255;
+ }
+ if (p2j.isChrome)
+ {
+ canvasRenderer.copyImage(screenCapture, data, imageBufferView, lineWidth, lineHeight, 0);
+ }
+ else
+ {
+ data.set(imageBufferView, 0);
+ }
+ canvasRenderer.putImageData(screenCapture, x1, y1);
+ }
+
+ /**
+ * Apply the stroke to the next point given by its coordinates (x, y).
+ *
+ * @param {Number} x
+ * X coordinate of the point to be drawn.
+ * @param {Number} y
+ * Y coordinate of the point to be drawn.
+ */
+ this.strokePoint = function(x, y)
+ {
+ canvasRenderer.putImageData(image, x, y);
+ }
+
+ }
+
+ /**
+ * DefaultPathRenderer implements StrokeRenderer methods
+ */
+ DefaultPathRenderer.prototype = Object.create(StrokeRenderer.prototype);
+
+ /**
+ * Defines the constructor function
+ */
+ DefaultPathRenderer.prototype.constructor = DefaultPathRenderer;
+
+}