diff --git a/HISTORY.md b/HISTORY.md index 99bcf59..6a3b46a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,8 @@ # Release history +## v0.1.7 +Changed fileGroups option from array of file names to regular expression + ## v0.1.6 Updated dependencies diff --git a/lib/CanvasRenderer/FILTERS.js b/lib/CanvasRenderer/FILTERS.js index 95efe1a..abd9393 100644 --- a/lib/CanvasRenderer/FILTERS.js +++ b/lib/CanvasRenderer/FILTERS.js @@ -1,7 +1,5 @@ 'use strict'; -var Canvas = require('canvas'); - // TODO: // - bevel filter // - gradient glow filter diff --git a/lib/CanvasRenderer/SwfImgRenderer/PngWriter.js b/lib/CanvasRenderer/SwfImgRenderer/PngWriter.js index 986b305..762fa40 100644 --- a/lib/CanvasRenderer/SwfImgRenderer/PngWriter.js +++ b/lib/CanvasRenderer/SwfImgRenderer/PngWriter.js @@ -71,6 +71,7 @@ PngWriter.prototype._addChunk = function (name, data, len) { var buf = new Buffer(len + 12, 'binary'); buf.writeUInt32BE(len, 0); buf.write(name, 4, 4); + // console.log('chunk type', name, JSON.stringify(data)); if (typeof data !== 'string') { data.copy(buf, 8, 0, len); } else { diff --git a/lib/CanvasRenderer/SwfImgRenderer/index.js b/lib/CanvasRenderer/SwfImgRenderer/index.js index 608e075..e36352f 100644 --- a/lib/CanvasRenderer/SwfImgRenderer/index.js +++ b/lib/CanvasRenderer/SwfImgRenderer/index.js @@ -21,7 +21,6 @@ SwfImgRenderer.prototype._renderPng = function (swfObject, whenDone) { // Should never happen unless caller is wrong throw new Error('Invalid data for PNG file'); } - var self = this; this._inflate(swfObject.colorData, function (buffer) { swfObject.data = buffer; diff --git a/lib/CanvasRenderer/main.js b/lib/CanvasRenderer/main.js index 10b3729..da0a5ed 100644 --- a/lib/CanvasRenderer/main.js +++ b/lib/CanvasRenderer/main.js @@ -2,22 +2,30 @@ var SwfImgRenderer = require('./SwfImgRenderer/index'); /* List of known issues: - - drawImage does implicit conversion of image position to integer (due to node canvas, issue #395 on https://github.com/LearnBoost/node-canvas) + - Global Composite Operations Bug: source-in can result in an overflow if rendered image is bigger than the mask (due to node canvas, issue #416 on https://github.com/LearnBoost/node-canvas) + + - Global Composite Operations Bug (Another): source-in can result in dark outlines of the image when rotated + (due to node canvas, not reported) + - Alpha of gradient fill style bug (due to node canvas, issue #417 on https://github.com/LearnBoost/node-canvas) + - Drawing images of dimension (w, h) = (0, 0) or with a scale of 0 makes a canvas unsuable (due to node canvas, not reported) - - Another Global Composite Operations Bug: source-in can result in dark outlines of the image when rotated - (due to node canvas, not reported) + - putImageData does not always use the last updated data (seems to be due to node canvas, not reported) + - Path point positions need to be rounded to one decimal value when creating a vectorial path + (due to node canvas, not reported) + - When rendering images the size of the canvas could be too small if glows or shadows are being applied (Fix: consider glow and shadow dimensions when setting canvas dimension, increased dimension should be notified to the extractor) + - Not tested but probably does not work: rendering rotated shapes with an alpha blend mode will not have the same result as in flash */ diff --git a/lib/CanvasRenderer/prepareImages.js b/lib/CanvasRenderer/prepareImages.js index c958850..dc30606 100644 --- a/lib/CanvasRenderer/prepareImages.js +++ b/lib/CanvasRenderer/prepareImages.js @@ -25,7 +25,7 @@ CanvasRenderer.prototype._prepareImages = function () { imageContext.drawImage(img, 0, 0, img.width, img.height); } else { - console.warn('[CanvasRenderer.prepareImages] Image is empty', imageData.id); + console.warn('[CanvasRenderer.prepareImages] Image is empty', imageData.id, JSON.stringify(imageBuffer)); } nImagesReady += 1; diff --git a/lib/CanvasRenderer/renderImages.js b/lib/CanvasRenderer/renderImages.js index f627735..4373c84 100644 --- a/lib/CanvasRenderer/renderImages.js +++ b/lib/CanvasRenderer/renderImages.js @@ -152,7 +152,7 @@ function getGraphicsToRender(symbols, symbolList, images) { } return graphics; } - +var nBytes = 0; CanvasRenderer.prototype._renderGraphics = function (graphics, graphicDims, canvasses) { for (var id in graphics) { var canvas = new Canvas(); @@ -163,6 +163,7 @@ CanvasRenderer.prototype._renderGraphics = function (graphics, graphicDims, canv canvas.width = dimensions.sw; canvas.height = dimensions.sh; + nBytes += canvas.width * canvas.height * 4; if (graphic.isShape) { var transform = [dimensions.ratio, 0, 0, dimensions.ratio, - dimensions.dx, - dimensions.dy]; @@ -320,8 +321,8 @@ CanvasRenderer.prototype._renderImages = function (retry) { if (atlas) { imageList = [{ img: atlas, name: 'atlas' }]; } else { - // TODO: add an option to let the user choose whether he wants to create several - // several atlas or reduce the asset sizes when this situation happens + // TODO: add an option to let the user choose whether he wants to create + // several atlases or reduce the asset sizes when this situation happens // Atlas could not be extracted at current ratio // Reducing extraction ratio and attempting rendering once more diff --git a/lib/CanvasRenderer/vectorialRendering.js b/lib/CanvasRenderer/vectorialRendering.js index 98ba554..a2e0fc0 100644 --- a/lib/CanvasRenderer/vectorialRendering.js +++ b/lib/CanvasRenderer/vectorialRendering.js @@ -186,6 +186,7 @@ CanvasRenderer.prototype._drawShapes = function (shapes, canvas, context, transf } }; +// Due to a bug in cairo, path point positions have to be rounded CanvasRenderer.prototype._createPath = function (context, shapes, transform, pixelHinting) { context.beginPath(); var p, seg; @@ -238,7 +239,6 @@ CanvasRenderer.prototype._outlineShapes = function (context, shapes, transform, this._createPath(context, shapes, transform, pixelHinting); var s, color, alpha, scale; - context.save(); if (line.capStart) { diff --git a/lib/Gordon/parser.js b/lib/Gordon/parser.js index 9cf2138..973e606 100644 --- a/lib/Gordon/parser.js +++ b/lib/Gordon/parser.js @@ -1,4 +1,4 @@ -//See http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/swf/pdf/swf-file-format-spec.pdf +// See http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/swf/pdf/swf-file-format-spec.pdf 'use strict'; @@ -8,7 +8,7 @@ var Stream = require('./stream.js'); function SwfParser() {} module.exports = SwfParser; -// TODO: figure out if we cannot get rid of this 'nlizeMatrix' function +// TODO: figure out if we can get rid of this 'nlizeMatrix' function function nlizeMatrix(matrix) { return { scaleX: matrix.scaleX * 20, @@ -62,7 +62,6 @@ SwfParser.prototype = { } else if (sign === signatures.SWF) { this._parseSwf(stream, cb); } else { - console.log('youhou!!'); cb('Invalid SWF file: ' + swfName); } }, @@ -75,9 +74,9 @@ SwfParser.prototype = { // to extract regular swf files. // It should possible to determine the symbols of the swl table from the dofus database - //Special table at the head of a ".swl" file; we did not find why this is useful... - //Maybe to be able to easily look for which symbols are defined in a .swf without - //having to parse/decompress it all. + // Special table at the head of a ".swl" file; we did not find why this is useful... + // Maybe to be able to easily look for which symbols are defined in a .swf without + // having to parse/decompress it all. _readSwlTable: function (stream) { var sign = stream.readString(2); if (sign[0] !== 'L' || sign.charCodeAt(1) !== 0) { @@ -771,8 +770,8 @@ SwfParser.prototype = { var depth = stream.readUI16(); var hasCharacter = flags & f.HAS_CHARACTER; var hasImage = flags2 & f.HAS_IMAGE; - var className = ((flags2 & f.HAS_CLASS_NAME) || (hasImage && hasCharacter)) ? stream.readString : undefined; - var character = { depth: depth }; + var baseClass = ((flags2 & f.HAS_CLASS_NAME) || (hasImage && hasCharacter)) ? stream.readString : undefined; + var character = { depth: depth, baseClass: baseClass }; if (hasCharacter) { var objId = stream.readUI16(); diff --git a/lib/Helper/generateExportList.js b/lib/Helper/generateExportList.js index 8349678..ab9526c 100644 --- a/lib/Helper/generateExportList.js +++ b/lib/Helper/generateExportList.js @@ -121,15 +121,29 @@ // } -function generateExportList(symbols, classList) { +function generateExportList(symbols, classList, attributeFilter) { var symbolList = []; + // Creating list of symbols to export + // Starting with the symbols corresponding to the class to export var symbolsToVisit = []; for (var className in classList) { var classId = classList[className]; - symbolsToVisit.push(classId); + + if (attributeFilter) { + var classSymbol = symbols[classId]; + for (var a = 0; a < attributeFilter.length; a +=1) { + if (classSymbol[attributeFilter[a]]) { + // The class has the corresponding attribute, it is added for export + symbolsToVisit.push(classId); + } + } + } else { + symbolsToVisit.push(classId); + } } + // Including symbols that are descendants of the classes to export var visistedSymbols = {}; while (symbolsToVisit.length > 0) { var symbolId = symbolsToVisit.pop(); diff --git a/lib/Helper/groupClasses.js b/lib/Helper/groupClasses.js index a15b3fd..2603f7e 100644 --- a/lib/Helper/groupClasses.js +++ b/lib/Helper/groupClasses.js @@ -1,12 +1,11 @@ 'use strict'; function groupClasses(classList, classGroups, split) { - - // Grouping classes if (!split && Object.keys(classGroups).length === 0) { return [{ name: '', list: classList }]; } + // Creating list of classes that will be exported separately var splitName; var classSplits = {}; for (splitName in classGroups) { @@ -14,12 +13,12 @@ function groupClasses(classList, classGroups, split) { } var className; - var remainingClasses = []; + var remainingClasses = []; // List of classes that will be exported together for (className in classList) { var matchFound = false; for (splitName in classGroups) { - var splitRegEx = classGroups[splitName]; - if (className.match(splitRegEx)) { + var groupRegEx = classGroups[splitName]; + if (className.match(groupRegEx)) { classSplits[splitName][className] = classList[className]; matchFound = true; } diff --git a/lib/Helper/makeFileGroups.js b/lib/Helper/groupFiles.js similarity index 65% rename from lib/Helper/makeFileGroups.js rename to lib/Helper/groupFiles.js index 55620b1..fd5ce3d 100644 --- a/lib/Helper/makeFileGroups.js +++ b/lib/Helper/groupFiles.js @@ -5,10 +5,10 @@ function getFileName(uri) { return uri.substring(uri.lastIndexOf(separator) + 1, uri.lastIndexOf('.')); } -function makeFileGroups(uris, fileGroups) { +function groupFiles(uris, fileGroupsRegEx) { var fileGroupsArray = []; var u, fileName; - if (!fileGroups) { + if (!fileGroupsRegEx) { for (u = 0; u < uris.length; u += 1) { fileName = getFileName(uris[u]); fileGroupsArray.push({ input: [uris[u]], output: fileName }); @@ -16,30 +16,34 @@ function makeFileGroups(uris, fileGroups) { return fileGroupsArray; } + // Creating one group per file var fileGroupsObject = {}; for (u = 0; u < uris.length; u += 1) { fileName = getFileName(uris[u]); fileGroupsObject[fileName] = [uris[u]]; } - var output; - for (output in fileGroups) { - var groupFiles = fileGroups[output]; + for (output in fileGroupsRegEx) { var fileGroup = fileGroupsObject[output]; if (fileGroup === undefined) { fileGroup = []; fileGroupsObject[output] = fileGroup; } - for (var f = 0; f < groupFiles.length; f += 1) { - fileName = groupFiles[f]; + var groupRegEx = fileGroupsRegEx[output]; // pattern of the current group + for (u = 0; u < uris.length; u += 1) { + fileName = getFileName(uris[u]); if (fileName === output) { + // File name is identical to the output, therefore they are merged continue; } - var fileArray = fileGroupsObject[fileName]; - if (fileArray) { - fileGroup.push(fileArray[0]); + + // Merging file to group if it matches the pattern + if (fileName.match(groupRegEx)) { + fileGroup.push(uris[u]); + + // Removing the file as a stand-alone delete fileGroupsObject[fileName]; } } @@ -56,4 +60,4 @@ function makeFileGroups(uris, fileGroups) { return fileGroupsArray; } -module.exports = makeFileGroups; \ No newline at end of file +module.exports = groupFiles; \ No newline at end of file diff --git a/lib/Helper/index.js b/lib/Helper/index.js index 7d82750..4cfa8f7 100644 --- a/lib/Helper/index.js +++ b/lib/Helper/index.js @@ -8,7 +8,7 @@ module.exports.getClasses = require('./getClasses.js'); module.exports.getMains = require('./getMains.js'); module.exports.groupClasses = require('./groupClasses.js'); module.exports.filterClasses = require('./filterClasses.js'); -module.exports.makeFileGroups = require('./makeFileGroups.js'); +module.exports.groupFiles = require('./groupFiles.js'); module.exports.flattenAnimations = require('./flattenAnimations.js'); module.exports.simplifyAnimation = require('./simplifyAnimation.js'); module.exports.delocateMatrices = require('./delocateMatrices.js'); \ No newline at end of file diff --git a/lib/SwfObjectProcessor/createSymbols.js b/lib/SwfObjectProcessor/createSymbols.js index 52b543d..ebf4fb9 100644 --- a/lib/SwfObjectProcessor/createSymbols.js +++ b/lib/SwfObjectProcessor/createSymbols.js @@ -27,7 +27,6 @@ function createSymbol(swfObject) { break; case 'shape': - var shapes = swfObject.edges; var imagesArray = []; for (var s = 0; s < shapes.length; s += 1) { diff --git a/lib/index.js b/lib/index.js index 5f98d80..4327969 100644 --- a/lib/index.js +++ b/lib/index.js @@ -48,7 +48,6 @@ function Jeff() { this._classGroupName = undefined; // Name this._classGroupList = undefined; // Classes this._hierarchy = undefined; // Hierarchy of the symbols - } function JeffOptions(params) { @@ -86,6 +85,7 @@ function JeffOptions(params) { this.classGroups = params.classGroups || {}; this.fileGroups = params.fileGroups || {}; this.fileGroupRatios = params.fileGroupRatios || {}; + this.attributeFilter = params.attributeFilter; this.classRatios = params.classRatios; this.container = params.container; this.ignoreExpression = params.ignoreExpression; @@ -147,7 +147,7 @@ Jeff.prototype._extractFileGroups = function (swfUris, endExtractionCb) { var nbFiles = 0; var nbErrors = 0; - var filesPerGroup = helper.makeFileGroups(swfUris, this._options.fileGroups); + var filesPerGroup = helper.groupFiles(swfUris, this._options.fileGroups); console.log('Starting conversion of', swfUris.length, 'file(s)'); var self = this; @@ -274,7 +274,7 @@ Jeff.prototype._processFileGroup = function (nextGroupCb) { function (classGroup, nextClassListCb) { self._classGroupName = classGroup.name; self._classGroupList = classGroup.list; - self._symbolList = helper.generateExportList(self._symbols, self._classGroupList); + self._symbolList = helper.generateExportList(self._symbols, self._classGroupList, self._options.attributeFilter); self._renderer.renderSymbols(self, function (imageList, graphicProperties) { self._extractClassGroup(imageList, graphicProperties, nextClassListCb); @@ -303,7 +303,7 @@ Jeff.prototype._generateImageName = function (imgName) { if (this._options.exportAtRoot) { imgPath = path.basename(imgPath); } - + return path.join(this._options.outDir, imgPath + '.png'); }; diff --git a/package.json b/package.json index 110702c..710bec6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "jeff", "description": "Extracts Json meta-data and images from a SWF Flash file.", - "version": "0.1.6", + "version": "0.1.7", "private": false, "author": { "name": "Brice Chevalier",