var FS = require('fs');
var Fabric = require('fabric').fabric;

var json = JSON.parse(process.argv[2]);
var canvas = Fabric.createCanvasForNode(json['dimensions']['width'],json['dimensions']['height']);

var imagePath = json['sourceFile'];
console.log("Setting background image to " + imagePath);

function applyBackground(canvas) {
  FS.readFile(imagePath, function (err, blob) {
    if (err) throw err;

    var dimensions = json['dimensions'];
    img = {'width': dimensions['width'], 'height': dimensions['height'], 'src':blob};

    Fabric.Image.fromObject(img, function(fimg) {
      canvas.add(fimg.set('top', img.height/2).set('left',img.width/2));

      applyMarkup(canvas);
    });
  });
}

function applyMarkup(canvas) {
  var size = json['dimensions'];

  json['instructions'].forEach(function (e) {
    for (shapeName in e) {
      switch (shapeName) {
        case 'rectangle':
          console.log(e[shapeName]);
          shape = e[shapeName];
          shape['stroke'] = Math.max(Math.round(json['finalDimensions']['width'] / 300 * 2), 2);

          var rect = {
            left: parseInt(shape['from']['x']),
            top: parseInt(shape['from']['y']),
            width: parseInt(shape['size']['width']),
            height: parseInt(shape['size']['height']),
            strokeWidth: parseInt(shape['stroke']),
            stroke: shape['color'],
            fill: 'transparent'
          }

          canvas.add(new Fabric.Rect(rect));
          break;
        case 'circle':
          console.log('サークル：実装されていない動作');
          break;
        default:
          console.log('Invalid operation: ' . shapeName);
      }
    }

    writeCanvas(canvas);
  });
}

function writeCanvas(canvas) {
  var outstream = FS.createWriteStream(json['destinationFile']),
      stream = canvas.createJPEGStream({
        quality: 93
      });

  stream.on('data', function(chunk) {
    outstream.write(chunk);
  });
}

applyBackground(canvas);

@@ -141,43 +141,72 @@
 ode(
-json%5B'dimensions'%5D%5B'width'%5D,json%5B'd
+parseInt(json%5B'finalDimensions'%5D%5B'width'%5D),parseInt(json%5B'finalD
 imen
@@ -223,16 +223,17 @@
 eight'%5D)
+)
 ;%0A%0Avar i
@@ -321,16 +321,186 @@
 Path);%0A%0A
+var crop = json%5B'instructions'%5D%5B'crop'%5D;%0Avar imageOffset = crop != %22undefined%22 ?%0A %7B'x':parseInt(crop%5B'from'%5D%5B'x'%5D),%0A  'y':parseInt(crop%5B'from'%5D%5B'y'%5D)%7D :%0A %7B'x':0,'y':0%7D;%0A%0A
 function
@@ -640,16 +640,67 @@
 ions'%5D;%0A
+    var finalDimensions = json%5B'finalDimensions'%5D;%0A
     img 
@@ -873,16 +873,35 @@
 height/2
+ - imageOffset%5B'y'%5D
 ).set('l
@@ -916,16 +916,35 @@
 .width/2
+ - imageOffset%5B'x'%5D
 ));%0A%0A   
@@ -1071,16 +1071,24 @@
 ctions'%5D
+%5B'draw'%5D
 .forEach
@@ -1187,45 +1187,8 @@
 e':%0A
-          console.log(e%5BshapeName%5D);%0A
     
@@ -1378,24 +1378,41 @@
 from'%5D%5B'x'%5D)
+-imageOffset%5B'x'%5D
 ,%0A          
@@ -1446,16 +1446,33 @@
 '%5D%5B'y'%5D)
+-imageOffset%5B'y'%5D
 ,%0A      
@@ -1709,104 +1709,796 @@
   %7D%0A
-%0A          canvas.add(new Fabric.Rect(rect));%0A          break;%0A        case 'circle':%0A          
+          //Fabric%E8%AA%BF%E6%95%B4%0A          rect%5B'top'%5D = rect%5B'top'%5D + rect%5B'height'%5D / 2 + rect%5B'strokeWidth'%5D / 2;%0A          rect%5B'left'%5D = rect%5B'left'%5D + rect%5B'width'%5D / 2 + rect%5B'strokeWidth'%5D / 2;%0A%0A          canvas.add(new Fabric.Rect(rect));%0A          break;%0A        case 'circle':%0A          shape = e%5BshapeName%5D;%0A          shape%5B'stroke'%5D = Math.max(Math.round(shape%5B'radius'%5D / 4), 5);%0A          %0A          var circle = %7B%0A            left: parseInt(shape%5B'from'%5D%5B'x'%5D)-imageOffset%5B'x'%5D,%0A            top: parseInt(shape%5B'from'%5D%5B'y'%5D)-imageOffset%5B'y'%5D,%0A            radius: parseInt(shape%5B'radius'%5D),%0A            strokeWidth: parseInt(shape%5B'stroke'%5D),%0A            stroke: shape%5B'color'%5D,%0A            fill: 'transparent'%0A          %7D;%0A          canvas.add(new Fabric.Circle(circle));%0A          //
 cons

Add crop, offset, and circle support