Skip to content

Commit

Permalink
Merge pull request #23 from aslansky/lwip
Browse files Browse the repository at this point in the history
Remove node-canvas as dependency
  • Loading branch information
aslansky committed Oct 10, 2014
2 parents d57557e + 6003db6 commit d97e11e
Show file tree
Hide file tree
Showing 11 changed files with 268 additions and 189 deletions.
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
language: node_js
node_js:
- '0.10'
before_install:
- sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++
after_script:
- npm run coveralls
10 changes: 8 additions & 2 deletions bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@ var opts = require('nomnom')
default: '../images',
help: 'http path to images on the web server (relative to css path or absolute path)'
})
.option('format', {
abbr: 'f',
choices: ['png', 'jpg'],
default: 'png',
help: 'output format of the sprite (png or jpg)'
})
.option('name', {
abbr: 'n',
default: 'sprite.png',
help: 'name of sprite file'
default: 'sprite',
help: 'name of sprite file without file extension '
})
.option('processor', {
abbr: 'p',
Expand Down
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ var writeFile = function (file, enc, cb) {
var defaults = {
src: null,
out: '',
name: 'sprite.png',
name: 'sprite',
style: null,
format: 'png',
cssPath: '../images',
processor: 'css',
template: null,
Expand Down
194 changes: 115 additions & 79 deletions lib/css-sprite.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
'use strict';

var async = require('async');
var through2 = require('through2');
var Canvas = require('canvas');
var lodash = require('lodash');
var path = require('path');
var json2css = require('json2css');
var File = require('vinyl');
var imageinfo = require('imageinfo');
var layout = require('layout');
var replaceExtension = require('./replace-extension');
var Image = Canvas.Image;
var lwip = require('lwip');

// json2css template
json2css.addTemplate('sprite', require(path.join(__dirname, 'templates/sprite.js')));

module.exports = function (opt) {
opt = lodash.extend({}, {name: 'sprite.png', margin: 5, processor: 'css', cssPath: '../images', orientation: 'vertical'}, opt);
opt = lodash.extend({}, {name: 'sprite', format: 'png', margin: 5, processor: 'css', cssPath: '../images', orientation: 'vertical'}, opt);
opt.styleExtension = (opt.processor === 'stylus') ? 'styl' : opt.processor;
var ctxHeight = 0;
var ctxWidth = 0;
var layoutOrientation = opt.orientation === 'vertical' ? 'top-down' : opt.orientation === 'horizontal' ? 'left-right' : 'binary-tree';
var layer = layout(layoutOrientation);

function queue (file, img) {
var spriteName = replaceExtension(file.relative, '').replace(/\/|\\|\ /g, '-');
layer.addItem({
height: img.height + 2 * opt.margin,
width: img.width + 2 * opt.margin,
height: img.height() + 2 * opt.margin,
width: img.width() + 2 * opt.margin,
meta: {
name: spriteName,
img: img,
image: path.join(opt.cssPath, opt.name)
image: opt.cssPath + '/' + opt.name
}
});
}
Expand All @@ -45,41 +43,41 @@ module.exports = function (opt) {
cb(new Error('Streaming not supported'));
return; // ignore
}
var img = new Image();
img.onload = function () {
queue(file, img, cb);
cb();
return;
};
img.onerror = function (err) {
console.log('Ignoring ' + file.relative + ' -> ' + err.toString());
cb();
return;
};
img.src = file.contents;
lwip.open(file.contents, imageinfo(file.contents).format.toLowerCase(), function(err, img) {
if (!err) {
queue(file, img);
cb();
}
else {
console.log('Ignoring ' + file.relative + ' -> ' + err.toString());
cb();
}
});
}

function createCanvas (layerInfo) {
var canvas = new Canvas(layerInfo.width, layerInfo.height);
var ctx = canvas.getContext('2d');
lodash.each(layerInfo.items, function (sprite, index) {
ctx.drawImage(sprite.meta.img, sprite.x + opt.margin, sprite.y + opt.margin, sprite.width - opt.margin * 2, sprite.height - opt.margin * 2);
function createCanvas (layerInfo, cb) {
lwip.create(layerInfo.width, layerInfo.height, 'white', function (err, image) {
async.eachSeries(layerInfo.items, function (sprite, callback) {
image.paste(sprite.x + opt.margin, sprite.y + opt.margin, sprite.meta.img, callback);
}, function () {
cb(image);
});
});
return canvas;
}

function createNonRetinaCanvas (retinaCanvas) {
var width = Math.floor(retinaCanvas.width / 2);
var height = Math.floor(retinaCanvas.height / 2)
var canvas = new Canvas(width, height);
var ctx = canvas.getContext('2d');
ctx.drawImage(retinaCanvas, 0, 0, width, height);
return canvas;
function createNonRetinaCanvas (retinaCanvas, cb) {
var width = Math.floor(retinaCanvas.width() / 2);
var height = Math.floor(retinaCanvas.height() / 2);
retinaCanvas.clone(function(err, clone){
clone.resize(width, height, function (err, image) {
cb(image);
});
});
}

function createStyle (layerInfo, sprite, retinaSprite) {
var sprites = [];
lodash.each(layerInfo.items, function (sprite, index) {
lodash.each(layerInfo.items, function (sprite) {
sprites.push({
'name': sprite.meta.name,
'x': sprite.x + opt.margin,
Expand All @@ -96,11 +94,11 @@ module.exports = function (opt) {
sprites.unshift({
name: retinaSprite.relative,
type: 'retina',
image: (!opt.base64) ? path.join(opt.cssPath, retinaSprite.relative) : 'data:' + imageinfo(retinaSprite.canvas.toBuffer()).mimeType + ';base64,' + retinaSprite.canvas.toBuffer().toString('base64'),
total_width: sprite.canvas.width,
total_height: sprite.canvas.height
image: (!opt.base64) ? path.join(opt.cssPath, retinaSprite.relative) : 'data:' + imageinfo(retinaSprite.buffer).mimeType + ';base64,' + retinaSprite.buffer.toString('base64'),
total_width: sprite.canvas.width(),
total_height: sprite.canvas.height()
});

lodash(sprites).each(function (sprite, i) {
sprites[i].x = Math.floor(sprite.x / 2);
sprites[i].y = Math.floor(sprite.y / 2);
Expand All @@ -112,7 +110,7 @@ module.exports = function (opt) {
sprites.unshift({
name: sprite.relative,
type: 'sprite',
image: (!opt.base64) ? path.join(opt.cssPath, sprite.relative) : 'data:' + imageinfo(sprite.canvas.toBuffer()).mimeType + ';base64,' + sprite.canvas.toBuffer().toString('base64'),
image: (!opt.base64) ? path.join(opt.cssPath, sprite.relative) : 'data:' + imageinfo(sprite.buffer).mimeType + ';base64,' + sprite.buffer.toString('base64'),
total_width: sprite.canvas.width,
total_height: sprite.canvas.height
});
Expand All @@ -121,54 +119,92 @@ module.exports = function (opt) {
}

function createSprite (cb) {
var _this = this;
var layerInfo = layer.export();
var sprite, nonRetinaSprite, style;
if (layerInfo.items.length === 0) {
cb();
return; // ignore
}
sprite = {
base: opt.out,
relative: opt.name,
path: path.join(opt.out, opt.name),
canvas: createCanvas(layerInfo)
};

if (opt.retina) {
sprite.path = replaceExtension(sprite.path, '') + '-x2.png';
sprite.relative = replaceExtension(sprite.relative, '') + '-x2.png';
nonRetinaSprite = {
base: opt.out,
relative: opt.name,
path: path.join(opt.out, opt.name),
canvas: createNonRetinaCanvas(sprite.canvas)
};
}

if (!opt.base64) {
if (opt.retina) {
this.push(new File({
base: nonRetinaSprite.base,
path: nonRetinaSprite.path,
contents: new Buffer(nonRetinaSprite.canvas.toBuffer())
}));
async.waterfall([
function (callback) {
createCanvas(layerInfo, function (canvas) {
sprite = {
base: opt.out,
relative: opt.name + '.' + opt.format,
path: path.join(opt.out, opt.name + '.' + opt.format),
canvas: canvas
};
callback(null, sprite);
});
},
function (sprite, callback) {
if (opt.retina) {
sprite.path = replaceExtension(sprite.path, '') + '-x2.' + opt.format;
sprite.relative = replaceExtension(sprite.relative, '') + '-x2.' + opt.format;
createNonRetinaCanvas(sprite.canvas, function (canvas) {
nonRetinaSprite = {
base: opt.out,
relative: opt.name + '.' + opt.format,
path: path.join(opt.out, opt.name + '.' + opt.format),
canvas: canvas
};
callback(null, sprite, nonRetinaSprite);
});
}
else {
callback(null, sprite, null);
}
},
function (sprite, nonRetinaSprite, callback) {
if (nonRetinaSprite) {
nonRetinaSprite.canvas.toBuffer(opt.format, {}, function (err, buf) {
nonRetinaSprite.buffer = buf;
callback(null, sprite, nonRetinaSprite);
});
}
else {
callback(null, sprite, nonRetinaSprite);
}
},
function (sprite, nonRetinaSprite, callback) {
sprite.canvas.toBuffer(opt.format, {}, function (err, buf) {
sprite.buffer = buf;
callback(null, sprite, nonRetinaSprite);
});
},
function (sprite, nonRetinaSprite, callback) {
if (!opt.base64) {
if (nonRetinaSprite) {
_this.push(new File({
base: nonRetinaSprite.base,
path: nonRetinaSprite.path,
contents: nonRetinaSprite.buffer
}));
}
_this.push(new File({
base: sprite.base,
path: sprite.path,
contents: sprite.buffer
}));
}
callback(null, sprite, nonRetinaSprite);
},
function (sprite, nonRetinaSprite, callback) {
if (opt.style || opt.base64) {
style = opt.retina ? createStyle(layerInfo, nonRetinaSprite, sprite) : createStyle(layerInfo, sprite);
_this.push(new File({
base: !opt.base64 ? path.dirname(opt.style) : opt.out,
path: opt.style ? opt.style : path.join(opt.out, replaceExtension(opt.name, '.' + opt.styleExtension)),
contents: new Buffer(style)
}));
}
callback(null);
}
this.push(new File({
base: sprite.base,
path: sprite.path,
contents: new Buffer(sprite.canvas.toBuffer())
}));
}

if (opt.style || opt.base64) {
style = opt.retina ? createStyle(layerInfo, nonRetinaSprite, sprite) : createStyle(layerInfo, sprite);
this.push(new File({
base: !opt.base64 ? path.dirname(opt.style) : opt.out,
path: opt.style ? opt.style : path.join(opt.out, replaceExtension(opt.name, '.' + opt.styleExtension)),
contents: new Buffer(style)
}));
}
cb();
], function () {
cb();
});
}

return through2.obj(queueImages, createSprite);
Expand Down
34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "css-sprite",
"version": "0.8.0-beta2",
"version": "0.9.0-beta",
"description": "css sprite generator",
"license": "MIT",
"repository": {
Expand Down Expand Up @@ -43,31 +43,31 @@
"gruntplugin"
],
"dependencies": {
"vinyl-fs": "0.3.6",
"canvas": "^1.1.6",
"async": "^0.9.0",
"gaze": "^0.6.4",
"graceful-fs": "^3.0.3",
"imageinfo": "^1.0.4",
"json2css": "^5.2.1",
"layout": "~2.0.0",
"lodash": "^2.4.1",
"nomnom": "^1.8.0",
"vinyl": "^0.3.2",
"graceful-fs": "^3.0.2",
"lwip": "0.0.5",
"mkdirp": "^0.5.0",
"gaze": "^0.6.4",
"imageinfo": "^1.0.4",
"through2": "^0.6.1",
"mustache": "^0.8.2",
"layout": "~2.0.0"
"nomnom": "^1.8.0",
"through2": "^0.6.3",
"vinyl": "^0.4.3",
"vinyl-fs": "0.3.9"
},
"devDependencies": {
"mocha": "^1.21.4",
"mocha-lcov-reporter": "^0.0.1",
"coveralls": "^2.11.1",
"istanbul": "^0.3.0",
"coveralls": "^2.11.2",
"istanbul": "^0.3.2",
"should": "^4.0.4",
"async": "^0.9.0",
"stylus": "^0.47.3",
"node-sass": "^0.9.3",
"less": "^1.7.4",
"clean-css": "^2.2.13",
"stylus": "^0.49.1",
"node-sass": "^0.9.6",
"less": "^1.7.5",
"clean-css": "^2.2.16",
"grunt": "^0.4.5"
}
}
Loading

0 comments on commit d97e11e

Please sign in to comment.