Skip to content

Commit

Permalink
port unit tests to mocha and chai, add img diff example tests, add de…
Browse files Browse the repository at this point in the history
…bug playground, setup travis
  • Loading branch information
gwwar committed Jun 17, 2015
1 parent 715ce44 commit 92ea35c
Show file tree
Hide file tree
Showing 36 changed files with 7,692 additions and 3,623 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
.idea/
.idea/
.node_modules/
node_modules/
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
language: node_js
node_js:
- "0.10"
before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
56 changes: 53 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Canvas2Svg
Canvas2Svg [![Build Status](https://travis-ci.org/gwwar/canvas2svg.svg?branch=master)](https://travis-ci.org/gwwar/canvas2svg)
==========
This library turns your Canvas into SVG using javascript. In other words, this library lets you build an SVG document using the canvas api. Why use it?
This library turns your Canvas into SVG using javascript. In other words, this library lets you build an SVG document
using the canvas api. Why use it?
* You have a canvas drawing you want to persist as an SVG file.
* You like exporting things.
* Because you didn't want to transform your custom file format to SVG.
Expand All @@ -11,7 +12,8 @@ http://gliffy.github.io/canvas2svg/

How it works
==========
We create a mock 2d canvas context. Use the canvas context like you would on a normal canvas. As you call methods, we build up a scene graph in SVG. Yay!
We create a mock 2d canvas context. Use the canvas context like you would on a normal canvas. As you call methods, we
build up a scene graph in SVG. Yay!

Usage
==========
Expand All @@ -31,8 +33,56 @@ var mySerializedSVG = ctx.getSerializedSvg(); //true here, if you need to conver
var svg = ctx.getSvg();
```

Tests
==========
To run tests:
```
npm install
npm test
```

To run tests against Chrome and Firefox, call karma directly. This is not the default npm test due to the limited
browser selection in travis.
```
npm install karma-cli -g
karma start
```

Debug
=========
Play with canvas2svg in the provided test/playground.html or run test locally in your browser in test/testrunner.html


Add An Example Case
=========
Add a test file to the test/example folder. In your file make sure to add the drawing function to the global `C2S_EXAMPLES`,
with your filename as a key. For example `test\example\linewidth.js` should look something like:
```javascript
window.C2S_EXAMPLES['linewidth'] = function(ctx) {
for (var i = 0; i < 10; i++){
ctx.lineWidth = 1+i;
ctx.beginPath();
ctx.moveTo(5+i*14,5);
ctx.lineTo(5+i*14,140);
ctx.stroke();
}
};
```
install gulp globally if you haven't done so already
```
npm install -g gulp
```
Then run the following to update playground.html and testrunner.html
```
gulp
```
You should now be able to select your new example from playground.html or see it run in testrunner.html

If you find a bug, or want to add functionality, please add a new test case and include it with your pull request.

Updates
==========
- v1.0.14 bugfix for gradients, move __createElement to scoped createElement function, so all classes have access.
- v1.0.13 set paint order before stroke and fill to make them behavior like canvas
- v1.0.12 Implementation of ctx.prototype.arcTo.
- v1.0.11 call lineTo instead moveTo in ctx.arc, fixes closePath issue and straight line issue
Expand Down
76 changes: 38 additions & 38 deletions canvas2svg.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*!!
* Canvas 2 Svg v1.0.13
* Canvas 2 Svg v1.0.14
* A low level canvas to SVG converter. Uses a mock canvas context to build an SVG document.
*
* Licensed under the MIT license:
Expand Down Expand Up @@ -72,6 +72,29 @@
return mapping[textBaseline] || mapping.alphabetic;
}

/**
* Creates the specified svg element
* @private
*/
function createElement(elementName, properties, resetFill) {
if (typeof properties === "undefined") {
properties = {};
}

var element = document.createElementNS("http://www.w3.org/2000/svg", elementName),
keys = Object.keys(properties), i, key;
if(resetFill) {
//if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black.
element.setAttribute("fill", "none");
element.setAttribute("stroke", "none");
}
for(i=0; i<keys.length; i++) {
key = keys[i];
element.setAttribute(key, properties[key]);
}
return element;
}

// Unpack entities lookup where the numbers are in radix 32 to reduce the size
// entity mapping courtesy of tinymce
namedEntities = createNamedToNumberedLookup(
Expand Down Expand Up @@ -183,7 +206,7 @@
* Adds a color stop to the gradient root
*/
CanvasGradient.prototype.addColorStop = function(offset, color) {
var stop = this.__createElement("stop"), regex, matches;
var stop = createElement("stop"), regex, matches;
stop.setAttribute("offset", offset);
if(color.indexOf("rgba") !== -1) {
//separate alpha value, since webkit can't handle it
Expand Down Expand Up @@ -262,29 +285,6 @@
this.__root.appendChild(this.__currentElement);
};

/**
* Creates the specified svg element
* @private
*/
ctx.prototype.__createElement = function(elementName, properties, resetFill) {
if (typeof properties === "undefined") {
properties = {};
}

var element = document.createElementNS("http://www.w3.org/2000/svg", elementName),
keys = Object.keys(properties), i, key;
if(resetFill) {
//if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black.
element.setAttribute("fill", "none");
element.setAttribute("stroke", "none");
}
for(i=0; i<keys.length; i++) {
key = keys[i];
element.setAttribute(key, properties[key]);
}
return element;
};

/**
* Applies default canvas styles to the context
* @private
Expand Down Expand Up @@ -426,7 +426,7 @@
* Will generate a group tag.
*/
ctx.prototype.save = function() {
var group = this.__createElement("g"), parent = this.__closestGroupOrSvg();
var group = createElement("g"), parent = this.__closestGroupOrSvg();
this.__groupStack.push(parent);
parent.appendChild(group);
this.__currentElement = group;
Expand All @@ -451,7 +451,7 @@
//if the current element has siblings, add another group
var parent = this.__closestGroupOrSvg();
if(parent.childNodes.length > 0) {
var group = this.__createElement("g");
var group = createElement("g");
parent.appendChild(group);
this.__currentElement = group;
}
Expand Down Expand Up @@ -509,7 +509,7 @@
this.__currentDefaultPath = "";
this.__currentPosition = {};

path = this.__createElement("path", {}, true);
path = createElement("path", {}, true);
parent = this.__closestGroupOrSvg();
parent.appendChild(path);
this.__currentElement = path;
Expand Down Expand Up @@ -732,7 +732,7 @@
*/
ctx.prototype.fillRect = function(x, y, width, height){
var rect, parent;
rect = this.__createElement("rect", {
rect = createElement("rect", {
x : x,
y : y,
width : width,
Expand All @@ -753,7 +753,7 @@
*/
ctx.prototype.strokeRect = function(x, y, width, height){
var rect, parent;
rect = this.__createElement("rect", {
rect = createElement("rect", {
x : x,
y : y,
width : width,
Expand All @@ -771,7 +771,7 @@
*/
ctx.prototype.clearRect = function(x, y, width, height) {
var rect, parent = this.__closestGroupOrSvg();
rect = this.__createElement("rect", {
rect = createElement("rect", {
x : x,
y : y,
width : width,
Expand All @@ -786,7 +786,7 @@
* Returns a canvas gradient object that has a reference to it's parent def
*/
ctx.prototype.createLinearGradient = function(x1, y1, x2, y2){
var grad = this.__createElement("linearGradient", {
var grad = createElement("linearGradient", {
id : randomString(this.__ids),
x1 : x1+"px",
x2 : x2+"px",
Expand All @@ -803,7 +803,7 @@
* Returns a canvas gradient object that has a reference to it's parent def
*/
ctx.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){
var grad = this.__createElement("radialGradient", {
var grad = createElement("radialGradient", {
id : randomString(this.__ids),
cx : x1+"px",
cy : y1+"px",
Expand Down Expand Up @@ -855,7 +855,7 @@
*/
ctx.prototype.__wrapTextLink = function(font, element) {
if(font.href) {
var a = this.__createElement("a");
var a = createElement("a");
a.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", font.href);
a.appendChild(element);
return a;
Expand All @@ -874,7 +874,7 @@
ctx.prototype.__applyText = function(text, x, y, action) {
var font = this.__parseFont(),
parent = this.__closestGroupOrSvg(),
textElement = this.__createElement("text", {
textElement = createElement("text", {
"font-family" : font.family,
"font-size" : font.size,
"font-style" : font.style,
Expand Down Expand Up @@ -963,9 +963,9 @@
*/
ctx.prototype.clip = function(){
var group = this.__closestGroupOrSvg(),
clipPath = this.__createElement("clipPath"),
clipPath = createElement("clipPath"),
id = randomString(this.__ids),
newGroup = this.__createElement("g");
newGroup = createElement("g");

group.removeChild(this.__currentElement);
clipPath.setAttribute("id", id);
Expand Down Expand Up @@ -1043,7 +1043,7 @@
this.__currentElement = currentElement;
} else if(image.nodeName === "CANVAS" || image.nodeName === "IMG") {
//canvas or image
svgImage = this.__createElement("image");
svgImage = createElement("image");
svgImage.setAttribute("width", dw);
svgImage.setAttribute("height", dh);
svgImage.setAttribute("preserveAspectRatio", "none");
Expand Down
31 changes: 31 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"use strict";

var gulp = require('gulp');
var fs = require('fs');
var path = require('path');
var cheerio = require('cheerio');


function updateExample(filename) {
var playground = fs.readFileSync(path.join(__dirname, filename), {'encoding': 'utf8'});
var filenames = fs.readdirSync(path.join(__dirname,'test/example'));
var $ = cheerio.load(playground);
var $examples = $('#examples');
var $select = $('#select');
$examples.empty();
$select.empty();
filenames.forEach(function(filename) {
var name = filename.replace('.js', '');
$examples.append($('<script type="text/javascript" src="example/'+filename+'"></script>'));
$select.append($('<option value="'+name+'">'+name+'</option>'));
});
fs.writeFileSync(path.join(__dirname, filename), $.html(), {'encoding': 'utf8'})
}

// run this after adding an example file to update playground.html, and testrunner.html
gulp.task('update_examples', function() {
updateExample('test/playground.html');
updateExample('test/testrunner.html');
});

gulp.task('default', ['update_examples']);
24 changes: 0 additions & 24 deletions jasmine-tests/SpecRunner.html

This file was deleted.

57 changes: 0 additions & 57 deletions jasmine-tests/canvassvg.html

This file was deleted.

Loading

0 comments on commit 92ea35c

Please sign in to comment.