=== 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 2015-10-15 09:00:17 +0000 +++ src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.canvas_renderer.js 2015-10-16 11:35:16 +0000 @@ -301,7 +301,39 @@ this.pixData[1] = color[1]; this.pixData[2] = color[2]; - this.putImageData(this.ctx, this.pixel, x, y); + this.putImageData(this.pixel, x, y); +}; + +/** + * If the pixel location is outside of the last clipped rectangle return false, otherwise + * return true. + * + * @param {Number} x + * X coordinate of the pixel to be checked. + * @param {Number} y + * Y coordinate of the pixel to be checked. + * + * @return {Boolean} + * The boolean value indicates the given pixel is in the last clipping region. + */ +CanvasRenderer.prototype.isInClipRegion = function(x, y) +{ + var lastClip = this.lastClippedRegion(true); + + if (lastClip != undefined) + { + var top = lastClip.y; + var bottom = lastClip.y + lastClip.height - 1; + var left = lastClip.x; + var right = lastClip.x + lastClip.width - 1; + + if (y < top || y > bottom || x < left || x > right) + { + return false; + } + } + + return true; }; /** @@ -309,33 +341,33 @@ *

* If the location is ouside of the last clipped rectangle, then this is a no-op. * - * @param {CanvasRenderingContext2D} ctx - * The canvas 2D graphics context on which to draw. - * @param {Image} pixel - * The pixel to be drawn. + * @param {ImageData} imageData + * The imageData to be drawn. * @param {Number} x * X coordinate of the pixel to be drawn. * @param {Number} y * Y coordinate of the pixel to be drawn. */ -CanvasRenderer.prototype.putImageData = function(ctx, pixel, x, y) -{ - var lastClip = this.lastClippedRegion(true); - - if (lastClip != undefined) - { - var top = lastClip.y; - var bottom = lastClip.y + lastClip.height - 1; - var left = lastClip.x; - var right = lastClip.x + lastClip.width - 1; - - if (y < top || y > bottom || x < left || x > right) - { - return; - } - } - - ctx.putImageData(pixel, x, y); +CanvasRenderer.prototype.putImageData = function(imageData, x, y) +{ + this.ctx.putImageData(imageData, x, y); +}; + +/** + * Creates a new ImageData object with the specified width and height. The new object is filled + * with transparent black pixels. + * + * @param {Number} width + * The image width in pixels. + * @param {Number} height + * The image height in pixels. + * + * @return {ImageData} + * The ImageData object with the specified width and height. + */ +CanvasRenderer.prototype.createImageData = function(width, height) +{ + return this.ctx.createImageData(width, height); }; /** @@ -361,14 +393,26 @@ */ CanvasRenderer.prototype.drawLineSegment = function(ctx, x1, y1, x2, y2, color) { + // holds the line pixels to draw + var path = []; + x1 = x1 + this.origin.x; x2 = x2 + this.origin.x; y1 = y1 + this.origin.y; y2 = y2 + this.origin.y; - // holds the line pixels to draw - var path = []; + // intersect with clipping region + var d = this.cutLine(x1, y1, x2, y2); + if (d === null) + { + return path; + } + x1 = d[0]; + y1 = d[1]; + x2 = d[2]; + y2 = d[3]; + var dx = Math.abs(x2 - x1); var dy = Math.abs(y2 - y1); @@ -484,7 +528,7 @@ CanvasRenderer.prototype.strokeLineSegment = function(ctx, x1, y1, x2, y2, color) { var path = this.drawLineSegment(ctx, x1, y1, x2, y2, color); - this.strokesManager.applyStrokeToPath(this.ctx, + this.strokesManager.applyStrokeToPath(this, this.strokeStyleId, this.strokeWidth, color, @@ -579,7 +623,7 @@ this.drawLine(ctx, x + width - 1 - inset, y + height - inset, x + 1, y + height - inset, color, path); this.drawLine(ctx, x, y + height - inset, x, y + 1, color, path);// close the path - this.strokesManager.applyStrokeToPath(this.ctx, + this.strokesManager.applyStrokeToPath(this, this.strokeStyleId, this.strokeWidth, color, @@ -635,7 +679,7 @@ data[p + 3] = (imgData[offset + 3] * alpha + data[p + 3] * beta) >> 8; }; }; - this.putImageData(ctx, img, this.origin.x + x, this.origin.y + y); + this.putImageData(img, this.origin.x + x, this.origin.y + y); }; /** @@ -712,7 +756,7 @@ this.drawLine(ctx, rightUpX, rightUpY, rightDownX, rightDownY, color, path); this.drawLine(ctx, bottomLeftX, bottomLeftY, bottomRightX, bottomRightY, color, path); this.drawLine(ctx, leftUpX, leftUpY, leftDownX, leftDownY, color, path); - this.strokesManager.applyStrokeToPath(this.ctx, + this.strokesManager.applyStrokeToPath(this, this.strokeStyleId, this.strokeWidth, color, @@ -790,7 +834,7 @@ var path = [];// create new pixels path to draw this.drawLine(ctx, x, y, x + width - 2 - inset, y, current, path); this.drawLine(ctx, x, y + 1, x, y + height - 1 - inset, current, path); - this.strokesManager.applyStrokeToPath(this.ctx, + this.strokesManager.applyStrokeToPath(this, this.strokeStyleId, this.strokeWidth, current, @@ -802,7 +846,7 @@ path = []; // create new pixels path to draw this.drawLine(ctx, x + 1, y + height - 1 - inset, x + width - 1 - inset, y + height - 1 - inset, current, path); this.drawLine(ctx, x + width - 1 - inset, y, x + width - 1 - inset, y + height - 2, current, path); - this.strokesManager.applyStrokeToPath(this.ctx, + this.strokesManager.applyStrokeToPath(this, this.strokeStyleId, this.strokeWidth, current, @@ -880,7 +924,7 @@ CanvasRenderer.prototype.strokePolygon = function(ctx, xPoints, yPoints, num, color, fill) { var path = this.drawPolygon(ctx, xPoints, yPoints, num, color, fill); - this.strokesManager.applyStrokeToPath(this.ctx, + this.strokesManager.applyStrokeToPath(this, this.strokeStyleId, this.strokeWidth, color, @@ -1100,6 +1144,83 @@ } /** + * Calculates the intersection of the given line segment with the last clipping region. + * + * @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. + * + * @return {Array} + * The line intersection with the last clipping region in the form of this array + * [new_x1, new_y1, new_x2, new_y2]. + */ +CanvasRenderer.prototype.cutLine = function (x1, y1, x2, y2) +{ + var lastClip = this.lastClippedRegion(true); + //xa, ya xb, yb is normalized region covered this line segment + var xa; + var xb; + var incx = (x1 < x2); + if (incx) + { + xa = x1; + xb = x2; + } + else + { + xa = x2; + xb = x1; + } + var ya; + var yb; + var incy = (y1 < y2); + if (incy) + { + ya = y1; + yb = y2; + } + else + { + ya = y2; + yb = y1; + } + + if (lastClip != undefined) + { + var top = lastClip.y; + var bottom = lastClip.y + lastClip.height - 1; + var left = lastClip.x; + var right = lastClip.x + lastClip.width - 1; + + if (yb < top || ya > bottom || xb < left || xa > right) + { + return null; + } + xb = Math.min(right, xb); + xa = Math.max(left, xa); + yb = Math.min(bottom, yb); + ya = Math.max(top, ya); + } + // check that it is vertical or horizontal + if ((x1 == x2) || (y1 == y2)) + { + return [xa, ya, xb, yb]; + } + var fxa; + var fxb; + + fxa = (y1 * (x2 - xa) / (x2 - x1)) + (y2 * (xa - x1) / (x2 - x1)); + fxb = (y1 * (x2 - xb) / (x2 - x1)) + (y2 * (xb - x1) / (x2 - x1)); + + return [xa, fxa, xb, fxb]; +} + +/** * Remove the most recently added rectangle from the current clipping region. The graphics * context state is popped to restore the previously used values. */ @@ -1272,7 +1393,7 @@ this.replay(); // re-blit the previously drawn content - this.putImageData(this.ctx, oldPixels, 0, 0); + this.putImageData(oldPixels, 0, 0); }; /** === 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-09-21 18:08:56 +0000 +++ src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.strokes.js 2015-10-16 11:32:28 +0000 @@ -55,7 +55,8 @@ SPECIFIED_WIDTH : 1, DOTTED : 2, DOTTED_SMALL : 3, - DOTTED_SMALL_THIN : 4 + DOTTED_SMALL_THIN : 4, + DOTTED_LARGE : 5 }; var LineStroke = @@ -70,7 +71,10 @@ DOT_LINE_WIDTH : 1.0, /** Dotted thin line width. */ - DOT_LINE_THIN_WIDTH : 0.5 + DOT_LINE_THIN_WIDTH : 0.5, + + /** */ + DOT_STEP_LARGE : 3 }; /** @@ -93,6 +97,11 @@ LineStroke.DOT_STEP_SMALL); /** + * Represents a dot style with 3 pixel to draw and then 3 pixel to pass. + */ + var dotLargeStroke = new BasicStroke(LineStroke.DOT_LINE_WIDTH, CAP_BUTT, JOIN_MITER, + 1.0, [LineStroke.DOT_STEP_LARGE, LineStroke.DOT_STEP_LARGE], 0); + /** * Represents a default style to draw a 1 pixel width solid line. */ var defaultStroke = new BasicStroke(1.0, CAP_SQUARE, JOIN_MITER, 10.0, null, 0.0); @@ -161,6 +170,8 @@ return dotSmallStroke; case LineStrokeEnum.DOTTED_SMALL_THIN: return dotSmallThinStroke; + case LineStrokeEnum.DOTTED_LARGE: + return dotLargeStroke; default: return defaultStroke; } @@ -169,7 +180,7 @@ /** * Returns the stroke path renderer. * - * @param {CanvasRenderingContext2D} context + * @param {CanvasRenderer} canvasRenderer * The canvas renderer. * @param {Number} strokeStyle * The stroke style id according to the LineStroke enumeration. @@ -181,18 +192,19 @@ * * @return The stroke path renderer. */ - function getStrokePathRenderer(context, strokeStyle, width, strokeColor) + function getStrokePathRenderer(canvasRenderer, strokeStyle, width, strokeColor) { var basicStroke = getLineStroke(strokeStyle, width); switch (strokeStyle) { case LineStrokeEnum.SPECIFIED_WIDTH: - return new WidenPathRenderer(context, basicStroke, strokeColor); + return new WidenPathRenderer(canvasRenderer, basicStroke, strokeColor); case LineStrokeEnum.DOTTED: case LineStrokeEnum.DOTTED_SMALL: case LineStrokeEnum.DOTTED_SMALL_THIN: - return new DotsPathRenderer(context, basicStroke, strokeColor); + case LineStrokeEnum.DOTTED_LARGE: + return new DotsPathRenderer(canvasRenderer, basicStroke, strokeColor); default: return { applyStroke : function (path) {} }; } @@ -202,7 +214,7 @@ * Apply the given stroke style to the JS native canvas renderer. * * @param {CanvasRenderingContext2D} context - * The canvas renderer. + * The canvas renderer context. * @param {Number} strokeStyle * The stroke style id. * @param {Number} width @@ -235,7 +247,7 @@ /** * Apply the given stroke style to the area outer bounds. * - * @param {CanvasRenderingContext2D} context + * @param {CanvasRenderer} canvasRenderer * The canvas renderer. * @param {Number} strokeStyle * The stroke style id. @@ -247,13 +259,10 @@ * @param {Array} path * The array of points that forms the outline of the target area. */ - this.applyStrokeToPath = function(context, strokeStyle, width, strokeColor, path) + this.applyStrokeToPath = function(canvasRenderer, strokeStyle, width, strokeColor, path) { - if (context instanceof CanvasRenderingContext2D) - { - var renderer = getStrokePathRenderer(context, strokeStyle, width, strokeColor); - renderer.applyStroke(path); - } + var renderer = getStrokePathRenderer(canvasRenderer, strokeStyle, width, strokeColor); + renderer.applyStroke(path); } /** @@ -280,7 +289,7 @@ /** * Used to draw dash patterns on lines of pixels. * - * @param {CanvasRenderingContext2D} context + * @param {CanvasRenderer} canvasRenderer * The canvas renderer. * @param {Object} basicStroke * The stroke style object. @@ -288,9 +297,9 @@ * The array of 3 integer values between 0 and 255 inclusive, representing * a stroke color. */ - function DotsPathRenderer(ctx, basicStroke, strokeColor) + function DotsPathRenderer(canvasRenderer, basicStroke, strokeColor) { - var pixel = ctx.createImageData(1, 1); + var pixel = canvasRenderer.createImageData(1, 1); var pixelData = pixel.data; pixelData[3] = 0xFF; @@ -367,7 +376,7 @@ pixelData[0] = strokeColor[0]; pixelData[1] = strokeColor[1]; pixelData[2] = strokeColor[2]; - ctx.putImageData(pixel, point.x, point.y); + canvasRenderer.putImageData(pixel, point.x, point.y); } } @@ -377,7 +386,7 @@ /** * Used to widen lines of pixels. * - * @param {CanvasRenderingContext2D} context + * @param {CanvasRenderer} canvasRenderer * The canvas renderer. * @param {Object} basicStroke * The stroke style object. @@ -385,10 +394,10 @@ * The array of 3 integer values between 0 and 255 inclusive, representing * a stroke color. */ - function WidenPathRenderer(ctx, basicStroke, strokeColor) + function WidenPathRenderer(canvasRenderer, basicStroke, strokeColor) { var width = basicStroke.getWidth(); - var image = ctx.createImageData(width, width); + var image = canvasRenderer.createImageData(width, width); var imageData = image.data; for (var i = 0; i < 4 * width * width; i += 4) @@ -410,7 +419,7 @@ for (var i = 0; i < path.length; i++) { var point = path[i]; - ctx.putImageData(image, point.x - (width >> 1), point.y - (width >> 1)); + canvasRenderer.putImageData(image, point.x - (width >> 1), point.y - (width >> 1)); } } }