From 31785d9a5b991b85e603b883c845fd4a5b6ec29a Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Fri, 23 Oct 2015 10:41:30 +1100 Subject: [PATCH 01/12] fix Render.SetPictureFilter --- lib/ext/render.js | 51 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/lib/ext/render.js b/lib/ext/render.js index cac22db..c16b60d 100644 --- a/lib/ext/render.js +++ b/lib/ext/render.js @@ -152,10 +152,10 @@ exports.requireExt = function(display, callback) } ext.FreePicture = function(pid) { - X.seq_num++; - X.pack_stream.pack('CCSL', [ext.majorOpcode, 7, 2, pid]); - X.pack_stream.flush(); - } + X.seq_num++; + X.pack_stream.pack('CCSL', [ext.majorOpcode, 7, 2, pid]); + X.pack_stream.flush(); + }; function floatToFix(f) { @@ -163,23 +163,42 @@ exports.requireExt = function(display, callback) } // see example of blur filter here: https://github.com/richoH/rxvt-unicode/blob/master/src/background.C - // TODO: not ready yet. ext.SetPictureFilter = function(pid, name, filterParams) { + if (filterParams === 0) + filterParams = [0]; + if (!filterParams) + filterParams = []; + if (!Array.isArray(filterParams)) + filterParams = [filterParams]; + X.seq_num++; - var reqLen = 2; //header + params + 1xStopfix+2xColors - var format = 'CCSLa'; - var params = [ext.majorOpcode, 30, reqLen, pid]; - /* - if (name == 'convolution') - { - reqLen += 2; - format += 'L'; - params.push(floatToFix(filterParams)); + var reqLen = 2; + var format = 'CCSLSxxp'; + var params = [ext.majorOpcode, 30, reqLen, pid, name.length, name + '\0']; + reqLen += xutil.padded_length(name.length+3)/4 + filterParams.length; + + if (name == 'nearest' || name == 'bilinear' || name == 'fast' || name == 'good' || name == 'best') { + if (filterParams.length != 0) { + throw 'Render.SetPictureFilter: "' + name + '" - unexpected parameters for filters"; + } + } else if (name == 'convolution' || ) { + if (filterParams.length < 2 || filterParams[0]*filterParams[1] !== filterParams.length + 2) { + throw 'Render.SetPictureFilter: "convolution" - incorrect matrix dimensions. Must be flat array [ w, h, elem1, elem2, ... ]'; + } + for (var i=0; i < filterParams.length; ++i) { + format += 'L'; + params.push(floatToFix(filterParams[i])); + } + } else if (name == 'binomial' || name == 'gaussian') { + if (filterParams.length < 2) { + throw 'Render.SetPictureFilter: "' + name + '" - incorrect number of parameters, must be exactly 1 number, instead got: ' + filterParams; + } + format += 'L'; + params.push(floatToFix(filterParams[0])); } else { - throw 'Not implemented filter ' + name; + throw 'Render.SetPictureFilter: unknown filter "' + name + '"'; } - */ params[2] = reqLen; X.pack_stream.pack(format, params); X.pack_stream.flush(); From 63fbe2e67112609e48da5ed74d1eb9fed036de5f Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Mon, 26 Oct 2015 09:54:37 +1100 Subject: [PATCH 02/12] add SetPictureTransform --- lib/ext/render.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/ext/render.js b/lib/ext/render.js index c16b60d..bbfc525 100644 --- a/lib/ext/render.js +++ b/lib/ext/render.js @@ -162,6 +162,22 @@ exports.requireExt = function(display, callback) return parseInt(f*65536); } + ext.SetPictureTransform = function(pid, matrix) { + X.seq_num++; + var format = 'CCSL'; + if (typeof matrix.length !== 9) + throw 'Render.SetPictureTransform: incorrect transform matrix. Must be array of 9 numbers'; + var params = [ext.majorOpcode, 28, 11, pid]; + for (var i=0; i < 9; ++i) { + format += 'L'; + if (typeof matrix[i] !== 'number') + throw 'Render.SetPictureTransform: matrix element must be a number'; + params.push(floatToFix(matrix[i])); + } + X.pack_stream.pack(format, params); + X.pack_stream.flush(); + }; + // see example of blur filter here: https://github.com/richoH/rxvt-unicode/blob/master/src/background.C ext.SetPictureFilter = function(pid, name, filterParams) { @@ -180,7 +196,7 @@ exports.requireExt = function(display, callback) if (name == 'nearest' || name == 'bilinear' || name == 'fast' || name == 'good' || name == 'best') { if (filterParams.length != 0) { - throw 'Render.SetPictureFilter: "' + name + '" - unexpected parameters for filters"; + throw 'Render.SetPictureFilter: "' + name + '" - unexpected parameters for filters'; } } else if (name == 'convolution' || ) { if (filterParams.length < 2 || filterParams[0]*filterParams[1] !== filterParams.length + 2) { From c5fb01edaacbc3128d24037a6bcaeec4812b2ffb Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Mon, 26 Oct 2015 10:09:01 +1100 Subject: [PATCH 03/12] added PictOp constant codes --- lib/ext/render.js | 75 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/lib/ext/render.js b/lib/ext/render.js index bbfc525..eebe912 100644 --- a/lib/ext/render.js +++ b/lib/ext/render.js @@ -198,7 +198,7 @@ exports.requireExt = function(display, callback) if (filterParams.length != 0) { throw 'Render.SetPictureFilter: "' + name + '" - unexpected parameters for filters'; } - } else if (name == 'convolution' || ) { + } else if (name == 'convolution') { if (filterParams.length < 2 || filterParams[0]*filterParams[1] !== filterParams.length + 2) { throw 'Render.SetPictureFilter: "convolution" - incorrect matrix dimensions. Must be flat array [ w, h, elem1, elem2, ... ]'; } @@ -600,5 +600,78 @@ exports.requireExt = function(display, callback) }; }); + ext.PictOp = { + Minimum: 0, + Clear: 0, + Src: 1, + Dst: 2, + Over: 3, + OverReverse: 4, + In: 5, + InReverse: 6, + Out: 7, + OutReverse: 8, + Atop: 9, + AtopReverse: 10, + Xor: 11, + Add: 12, + Saturate: 13, + Maximum: 13, + + /*, + * Operators only available in version 0.2, + */ + DisjointMinimum: 0x10, + DisjointClear: 0x10, + DisjointSrc: 0x11, + DisjointDst: 0x12, + DisjointOver: 0x13, + DisjointOverReverse: 0x14, + DisjointIn: 0x15, + DisjointInReverse: 0x16, + DisjointOut: 0x17, + DisjointOutReverse: 0x18, + DisjointAtop: 0x19, + DisjointAtopReverse: 0x1a, + DisjointXor: 0x1b, + DisjointMaximum: 0x1b, + + ConjointMinimum: 0x20, + ConjointClear: 0x20, + ConjointSrc: 0x21, + ConjointDst: 0x22, + ConjointOver: 0x23, + ConjointOverReverse: 0x24, + ConjointIn: 0x25, + ConjointInReverse: 0x26, + ConjointOut: 0x27, + ConjointOutReverse: 0x28, + ConjointAtop: 0x29, + ConjointAtopReverse: 0x2a, + ConjointXor: 0x2b, + ConjointMaximum: 0x2b, + + /*, + * Operators only available in version 0.11, + */ + BlendMinimum: 0x30, + Multiply: 0x30, + Screen: 0x31, + Overlay: 0x32, + Darken: 0x33, + Lighten: 0x34, + ColorDodge: 0x35, + ColorBurn: 0x36, + HardLight: 0x37, + SoftLight: 0x38, + Difference: 0x39, + Exclusion: 0x3a, + HSLHue: 0x3b, + HSLSaturation: 0x3c, + HSLColor: 0x3d, + HSLLuminosity: 0x3e, + BlendMaximum: 0x3e + }; + }); } From 5c72df00e5668bd146830863641c22d612cbb8aa Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Mon, 26 Oct 2015 10:18:13 +1100 Subject: [PATCH 04/12] added PolyEdge,PolyMode,Repeat,Subpixel and Filters constants --- lib/ext/render.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/lib/ext/render.js b/lib/ext/render.js index eebe912..a51f458 100644 --- a/lib/ext/render.js +++ b/lib/ext/render.js @@ -673,5 +673,39 @@ exports.requireExt = function(display, callback) BlendMaximum: 0x3e }; + ext.PolyEdge = { + Sharp: 0, + Smooth: 1 + }; + + ext.PolyMode = { + Precise: 0, + Imprecise: 1 + }; + + ext.Repeat = { + None: 0, + Normal: 1, + Pad: 2, + Reflect: 3 + }; + + ext.Subpixel = { + Unknown: 0 + HorizontalRGB: 1, + HorizontalBGR: 2, + VerticalRGB : 3, + VerticalBGR : 4, + None : 5 + }; + + ext.Filters = { + Nearest: 'nearest', + Bilinear: 'bilinear', + Convolution: 'convolution', + Fast: 'fast', + Good: 'good', + Best: 'best' + }; }); } From fa9dbe20005e939db529e3f1c1be169ca2ff722c Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Wed, 4 Nov 2015 16:44:25 +1100 Subject: [PATCH 05/12] add Render.AddTraps request --- examples/smoketest/trapezoids.js | 75 ++++++++++++++++++++++++++++++++ lib/ext/render.js | 24 +++++++--- 2 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 examples/smoketest/trapezoids.js diff --git a/examples/smoketest/trapezoids.js b/examples/smoketest/trapezoids.js new file mode 100644 index 0000000..42be062 --- /dev/null +++ b/examples/smoketest/trapezoids.js @@ -0,0 +1,75 @@ +var x11 = require('../../lib'); +var Exposure = x11.eventMask.Exposure; +var PointerMotion = x11.eventMask.PointerMotion; + +var draw; + +x11.createClient({ debug: true}, function(err, display) { + + var X = display.client; + var root = display.screen[0].root; + + var wid = X.AllocID(); + X.CreateWindow( + wid, root, + 0, 0, 800, 600, + 0, 0, 0, 0, + { + eventMask: Exposure|PointerMotion + } + ); + X.MapWindow(wid); + + + X.require('render', function(err, Render) { + + var pixMask = X.AllocID(); + X.CreatePixmap(pixMask, wid, 8, 600, 600); + var pictTraps = X.AllocID(); + Render.CreatePicture(pictTraps, pixMask, Render.a8); + + var pictWin = X.AllocID(); + Render.CreatePicture(pictWin, wid, Render.rgb24); + + var pictSolid = X.AllocID(); + r = 0.2; g = 0.2; b = 0.2; a = 1; + Render.CreateSolidFill(pictSolid, r, g, b, a); + + draw = function(x, y) { + var r, g, b, a; + + // fill window + //r = x/1000; g = x/1000; b = x/1000; a = 0.5; + r = 1; g = 1; b = 1; a = 0.5; + Render.FillRectangles(1, pictWin, [r, g, b, a], [0, 0, 1000, 1000]) + + // fill traps + r = 0; g = 0; b = 0; a = 0; + Render.FillRectangles(1, pictTraps, [r, g, b, a], [0, 0, 1000, 1000]) + + Render.AddTraps(pictTraps, 0, 0, [ + x, 200, y, + //150, 200, 50, + 5, 250, 300, + 110, 200, 310, + 50, 150, 500 + ]); + + + // (op, src, mask, dst, srcX, srcY, maskX, maskY, dstX, dstY, width, height) + //Render.Composite(Render.PictOp.Over, pictSolid, pictTraps, pictWin, 0, 0, 0, 0, 0, 0, 800, 600); + //Render.PictOp.Over + + Render.Composite(Render.PictOp.Over, pictSolid, pictTraps, pictWin, 0, 0, 0, 0, 0, 0, 800, 600); + }; + + }); + +}).on('error', function(err) { + //console.log(err); +}).on('event', function(ev) { + //console.log(ev); + if (ev.name == 'MotionNotify') { + draw(ev.x, ev.y); + } +}); diff --git a/lib/ext/render.js b/lib/ext/render.js index a51f458..30dc6f8 100644 --- a/lib/ext/render.js +++ b/lib/ext/render.js @@ -159,7 +159,7 @@ exports.requireExt = function(display, callback) function floatToFix(f) { - return parseInt(f*65536); + return parseInt(f*65535); } ext.SetPictureTransform = function(pid, matrix) { @@ -331,7 +331,7 @@ exports.requireExt = function(display, callback) var format = 'CCSCxxxLSSSS'; var params = [ext.majorOpcode, 26, reqLen, op, pid]; for (var j=0; j < 4; ++j) - params.push(color[j]); + params.push(floatToFix(color[j])); for (var i=0; i < rects.length; i+=4) { format += 'ssSS'; @@ -354,12 +354,13 @@ exports.requireExt = function(display, callback) .flush(); } + // note that Trapezoids is considered deprecated by Render extension ext.Trapezoids = function(op, src, srcX, srcY, dst, maskFormat, trapz) { X.seq_num++; var format = 'CCSCxxxLLLss'; var params = [ext.majorOpcode, 10, 6+trapz.length, op, src, dst, maskFormat, srcX, srcY]; - for (var i=0; i < trapz.length; i+=10) + for (var i=0; i < trapz.length; i++) { format += 'llllllllll'; for (var j=0; j < 10; ++j) @@ -367,7 +368,20 @@ exports.requireExt = function(display, callback) } X.pack_stream.pack(format, params); X.pack_stream.flush(); - } + }; + + ext.AddTraps = function(pic, offX, offY, trapList) { + X.seq_num++; + var format = 'CCSLss'; + var params = [ext.majorOpcode, 32, 3+trapList.length, pic, offX, offY]; + for (var i=0; i < trapList.length; i++) + { + format += 'l'; + params.push(floatToFix(trapList[i])); + } + X.pack_stream.pack(format, params); + X.pack_stream.flush(); + }; ext.Triangles = function(op, src, srcX, srcY, dst, maskFormat, tris) { @@ -691,7 +705,7 @@ exports.requireExt = function(display, callback) }; ext.Subpixel = { - Unknown: 0 + Unknown: 0, HorizontalRGB: 1, HorizontalBGR: 2, VerticalRGB : 3, From 39a9931cbfc690807bbfb8cbf436db96e163516b Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Fri, 6 Nov 2015 13:57:39 +1100 Subject: [PATCH 06/12] add example for AddTraps, SetPictureTransform and SetPictureFilter --- examples/smoketest/blur-convolution.js | 51 ++++++++++++++++++++ examples/smoketest/trapezoids.js | 64 +++++++++++++++++++++++--- 2 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 examples/smoketest/blur-convolution.js diff --git a/examples/smoketest/blur-convolution.js b/examples/smoketest/blur-convolution.js new file mode 100644 index 0000000..7d85089 --- /dev/null +++ b/examples/smoketest/blur-convolution.js @@ -0,0 +1,51 @@ +// the code is taken from https://github.com/mattlockyer/iat455/blob/6493c882f1956703133c1bffa1d7ee9a83741cbe/assignment1/assignment/effects/blur-effect-dyn.js +// (c) Matt Lockyer, https://github.com/mattlockyer + +function hypotenuse(x1, y1, x2, y2) { + var xSquare = Math.pow(x1 - x2, 2); + var ySquare = Math.pow(y1 - y2, 2); + return Math.sqrt(xSquare + ySquare); +} + +/* + * Generates a kernel used for the gaussian blur effect. + * + * @param dimension is an odd integer + * @param sigma is the standard deviation used for our gaussian function. + * + * @returns an array with dimension^2 number of numbers, all less than or equal + * to 1. Represents our gaussian blur kernel. + */ +function generateGaussianKernel(dimension, sigma) { + if (!(dimension % 2) || Math.floor(dimension) !== dimension || dimension<3) { + throw new Error( + 'The dimension must be an odd integer greater than or equal to 3' + ); + } + var kernel = []; + + var twoSigmaSquare = 2 * sigma * sigma; + var centre = (dimension - 1) / 2; + + for (var i = 0; i < dimension; i++) { + for (var j = 0; j < dimension; j++) { + var distance = hypotenuse(i, j, centre, centre); + + // The following is an algorithm that came from the gaussian blur + // wikipedia page [1]. + // + // http://en.wikipedia.org/w/index.php?title=Gaussian_blur&oldid=608793634#Mechanics + var gaussian = (1 / Math.sqrt( + Math.PI * twoSigmaSquare + )) * Math.exp((-1) * (Math.pow(distance, 2) / twoSigmaSquare)); + + kernel.push(gaussian); + } + } + + // Returns the unit vector of the kernel array. + var sum = kernel.reduce(function (c, p) { return c + p; }); + return kernel.map(function (e) { return e / sum; }); +} + +module.exports = generateGaussianKernel; diff --git a/examples/smoketest/trapezoids.js b/examples/smoketest/trapezoids.js index 42be062..7361629 100644 --- a/examples/smoketest/trapezoids.js +++ b/examples/smoketest/trapezoids.js @@ -1,9 +1,13 @@ +var _ = require('underscore'); var x11 = require('../../lib'); var Exposure = x11.eventMask.Exposure; var PointerMotion = x11.eventMask.PointerMotion; +var ButtonPress = x11.eventMask.ButtonPress; var draw; +var useConvo3 = true; + x11.createClient({ debug: true}, function(err, display) { var X = display.client; @@ -15,7 +19,7 @@ x11.createClient({ debug: true}, function(err, display) { 0, 0, 800, 600, 0, 0, 0, 0, { - eventMask: Exposure|PointerMotion + eventMask: Exposure|PointerMotion|ButtonPress } ); X.MapWindow(wid); @@ -23,6 +27,8 @@ x11.createClient({ debug: true}, function(err, display) { X.require('render', function(err, Render) { + Render.QueryFilters(console.log); + var pixMask = X.AllocID(); X.CreatePixmap(pixMask, wid, 8, 600, 600); var pictTraps = X.AllocID(); @@ -35,13 +41,44 @@ x11.createClient({ debug: true}, function(err, display) { r = 0.2; g = 0.2; b = 0.2; a = 1; Render.CreateSolidFill(pictSolid, r, g, b, a); - draw = function(x, y) { - var r, g, b, a; + var pixBuff = X.AllocID(); + X.CreatePixmap(pixBuff, wid, 24, 600, 600); + var pictBuff = X.AllocID(); + Render.CreatePicture(pictBuff, pixBuff, Render.rgb24); + + var convo5 = [ 5, 5, 0.0030, 0.0133, 0.0219, 0.0133, 0.0030, + 0.0133, 0.0596, 0.0983, 0.0596, 0.0133, + 0.0219, 0.0983, 0.1621, 0.0983, 0.0219, + 0.0133, 0.0596, 0.0983, 0.0596, 0.0133, + 0.0030, 0.0133, 0.0219, 0.0133, 0.0030]; + var convo3 = [3, 3, 0.01, 0.08, 0.01, 0.08, 0.64, 0.08, 0.01, 0.08, 0.01]; + + var convo5 = [21, 21].concat(require('./blur-convolution')(21, 11)); + + //Render.SetPictureFilter(pictBuff, 'convolution', convo3); + //Render.SetPictureFilter(pictTraps, 'convolution', convo3); + //Render.SetPictureFilter(pictBuff, 'bilinear', []); + Render.SetPictureFilter(pictBuff, 'best', []); + + draw1 = function(x, y) { + console.log('draw 1', x, y); + var r = 3 + 2*Math.floor(x / 100); + var convo = [r, r].concat(require('./blur-convolution')(r, r)); + Render.SetPictureFilter(pictBuff, 'convolution', convo); + + var a = (x-400)/500; + var m = [ + Math.cos(a), Math.sin(a), 0, + -Math.sin(a), Math.cos(a), 0, + 0, 0, 1 + ]; + // Render.SetPictureTransform(pictTraps, m) + + var r, g, b; // fill window - //r = x/1000; g = x/1000; b = x/1000; a = 0.5; r = 1; g = 1; b = 1; a = 0.5; - Render.FillRectangles(1, pictWin, [r, g, b, a], [0, 0, 1000, 1000]) + Render.FillRectangles(1, pictBuff, [r, g, b, a], [0, 0, 1000, 1000]) // fill traps r = 0; g = 0; b = 0; a = 0; @@ -60,16 +97,29 @@ x11.createClient({ debug: true}, function(err, display) { //Render.Composite(Render.PictOp.Over, pictSolid, pictTraps, pictWin, 0, 0, 0, 0, 0, 0, 800, 600); //Render.PictOp.Over - Render.Composite(Render.PictOp.Over, pictSolid, pictTraps, pictWin, 0, 0, 0, 0, 0, 0, 800, 600); + Render.Composite(Render.PictOp.Over, pictSolid, pictTraps, pictBuff, 0, 0, 0, 0, 0, 0, 800, 600); + Render.Composite(Render.PictOp.Over, pictBuff, 0, pictWin, 0, 0, 0, 0, 0, 0, 800, 600); + + }; + + draw = function(x, y) { + var f = _.debounce(function() { + draw1(x, y); + }, 100); + f(); }; }); }).on('error', function(err) { - //console.log(err); + console.log(err); }).on('event', function(ev) { //console.log(ev); if (ev.name == 'MotionNotify') { draw(ev.x, ev.y); + } else if (ev.name == 'ButtonPress') { + useConvo3 = !useConvo3; + draw(ev.x, ev.y); + //console.log(ev); } }); From a49c9adeb35116a011e09a6a16843d42bd51641a Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Sun, 8 Nov 2015 12:13:53 +1100 Subject: [PATCH 07/12] don't increment seq_num if exception is thrown --- lib/ext/render.js | 68 ++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/lib/ext/render.js b/lib/ext/render.js index 30dc6f8..ff3b9e0 100644 --- a/lib/ext/render.js +++ b/lib/ext/render.js @@ -32,7 +32,6 @@ exports.requireExt = function(display, callback) ext.QueryPictFormat = function(callback) { - X.seq_num++; X.pack_stream.pack('CCS', [ext.majorOpcode, 1, 1]); X.replies[X.seq_num] = [ function (buf, opt) { @@ -42,7 +41,7 @@ exports.requireExt = function(display, callback) var num_screens = res1[1]; var num_depths = res1[2]; var num_visuals = res1[3]; - var num_subpixel = res1[4]; + var num_subpixel = res1[4]; // formats list: var offset = 24; res.formats = []; @@ -58,11 +57,11 @@ exports.requireExt = function(display, callback) callback ]; X.pack_stream.flush(); + X.seq_num++; } ext.QueryFilters = function(callback) { - X.seq_num++; X.pack_stream.pack('CCSL', [ext.majorOpcode, 29, 2, display.screen[0].root]); X.replies[X.seq_num] = [ function(buf, opt) { @@ -90,6 +89,7 @@ exports.requireExt = function(display, callback) callback ]; X.pack_stream.flush(); + X.seq_num++; } var valueList = [ @@ -118,7 +118,6 @@ exports.requireExt = function(display, callback) ext.CreatePicture = function(pid, drawable, pictformat, values) { - X.seq_num++; var mask = 0; var reqLen = 5; // + (values + pad)/4 var format = 'CCSLLLL'; @@ -149,23 +148,30 @@ exports.requireExt = function(display, callback) } X.pack_stream.pack(format, params); X.pack_stream.flush(); + X.seq_num++; } ext.FreePicture = function(pid) { - X.seq_num++; X.pack_stream.pack('CCSL', [ext.majorOpcode, 7, 2, pid]); X.pack_stream.flush(); + X.seq_num++; }; function floatToFix(f) { - return parseInt(f*65535); + return parseInt(f*65536); + } + + function colorToFix(f) + { + if (f < 0) f = 0; + if (f > 1) f = 1; + return parseInt(f*65535); } ext.SetPictureTransform = function(pid, matrix) { - X.seq_num++; var format = 'CCSL'; - if (typeof matrix.length !== 9) + if (matrix.length !== 9) throw 'Render.SetPictureTransform: incorrect transform matrix. Must be array of 9 numbers'; var params = [ext.majorOpcode, 28, 11, pid]; for (var i=0; i < 9; ++i) { @@ -176,6 +182,7 @@ exports.requireExt = function(display, callback) } X.pack_stream.pack(format, params); X.pack_stream.flush(); + X.seq_num++; }; // see example of blur filter here: https://github.com/richoH/rxvt-unicode/blob/master/src/background.C @@ -188,10 +195,9 @@ exports.requireExt = function(display, callback) if (!Array.isArray(filterParams)) filterParams = [filterParams]; - X.seq_num++; var reqLen = 2; var format = 'CCSLSxxp'; - var params = [ext.majorOpcode, 30, reqLen, pid, name.length, name + '\0']; + var params = [ext.majorOpcode, 30, reqLen, pid, name.length, name]; reqLen += xutil.padded_length(name.length+3)/4 + filterParams.length; if (name == 'nearest' || name == 'bilinear' || name == 'fast' || name == 'good' || name == 'best') { @@ -199,7 +205,7 @@ exports.requireExt = function(display, callback) throw 'Render.SetPictureFilter: "' + name + '" - unexpected parameters for filters'; } } else if (name == 'convolution') { - if (filterParams.length < 2 || filterParams[0]*filterParams[1] !== filterParams.length + 2) { + if (filterParams.length < 2 || ((filterParams[0]*filterParams[1] + 2) !== filterParams.length) ) { throw 'Render.SetPictureFilter: "convolution" - incorrect matrix dimensions. Must be flat array [ w, h, elem1, elem2, ... ]'; } for (var i=0; i < filterParams.length; ++i) { @@ -218,19 +224,18 @@ exports.requireExt = function(display, callback) params[2] = reqLen; X.pack_stream.pack(format, params); X.pack_stream.flush(); + X.seq_num++; }; ext.CreateSolidFill = function(pid, r, g, b, a) { - X.seq_num++; - X.pack_stream.pack('CCSLSSSS', [ext.majorOpcode, 33, 4, pid, floatToFix(r), floatToFix(g), floatToFix(b), floatToFix(a)]); + X.pack_stream.pack('CCSLSSSS', [ext.majorOpcode, 33, 4, pid, colorToFix(r), colorToFix(g), colorToFix(b), colorToFix(a)]); X.pack_stream.flush(); + X.seq_num++; }; ext.RadialGradient = function(pid, p1, p2, r1, r2, stops) { - // TODO: merge with linear gradient - X.seq_num++; var reqLen = 9+stops.length*3; //header + params + 1xStopfix+2xColors var format = 'CCSLLLLLLLL'; var params = [ext.majorOpcode, 35, reqLen, pid]; @@ -255,15 +260,15 @@ exports.requireExt = function(display, callback) { format += 'SSSS'; for (var j=0; j < 4; ++j) - params.push(stops[i][1][j]); + params.push(colorToFix(stops[i][1][j])); } X.pack_stream.pack(format, params); X.pack_stream.flush(); + X.seq_num++; }; ext.LinearGradient = function(pid, p1, p2, stops) { - X.seq_num++; var reqLen = 7+stops.length*3; //header + params + 1xStopfix+2xColors var format = 'CCSLLLLLL'; var params = [ext.majorOpcode, 34, reqLen, pid]; @@ -287,15 +292,15 @@ exports.requireExt = function(display, callback) { format += 'SSSS'; for (var j=0; j < 4; ++j) - params.push(stops[i][1][j]); + params.push(colorToFix(stops[i][1][j])); } X.pack_stream.pack(format, params); X.pack_stream.flush(); + X.seq_num++; } ext.ConicalGradient = function(pid, center, angle, stops) { - X.seq_num++; var reqLen = 6+stops.length*3; //header + params + 1xStopfix+2xColors var format = 'CCSLLLLL'; var params = [ext.majorOpcode, 36, reqLen, pid]; @@ -318,20 +323,20 @@ exports.requireExt = function(display, callback) { format += 'SSSS'; for (var j=0; j < 4; ++j) - params.push(stops[i][1][j]); + params.push(colorToFix(stops[i][1][j])); } X.pack_stream.pack(format, params); X.pack_stream.flush(); + X.seq_num++; } ext.FillRectangles = function(op, pid, color, rects) { - X.seq_num++; var reqLen = 5+rects.length/2; var format = 'CCSCxxxLSSSS'; var params = [ext.majorOpcode, 26, reqLen, op, pid]; for (var j=0; j < 4; ++j) - params.push(floatToFix(color[j])); + params.push(colorToFix(color[j])); for (var i=0; i < rects.length; i+=4) { format += 'ssSS'; @@ -342,22 +347,22 @@ exports.requireExt = function(display, callback) } X.pack_stream.pack(format, params); X.pack_stream.flush(); + X.seq_num++; } ext.Composite = function(op, src, mask, dst, srcX, srcY, maskX, maskY, dstX, dstY, width, height) { - X.seq_num++; X.pack_stream.pack( 'CCSCxxxLLLssssssSS', [ext.majorOpcode, 8, 9, op, src, mask, dst, srcX, srcY, maskX, maskY, dstX, dstY, width, height] ) .flush(); + X.seq_num++; } // note that Trapezoids is considered deprecated by Render extension ext.Trapezoids = function(op, src, srcX, srcY, dst, maskFormat, trapz) { - X.seq_num++; var format = 'CCSCxxxLLLss'; var params = [ext.majorOpcode, 10, 6+trapz.length, op, src, dst, maskFormat, srcX, srcY]; for (var i=0; i < trapz.length; i++) @@ -368,10 +373,10 @@ exports.requireExt = function(display, callback) } X.pack_stream.pack(format, params); X.pack_stream.flush(); + X.seq_num++; }; ext.AddTraps = function(pic, offX, offY, trapList) { - X.seq_num++; var format = 'CCSLss'; var params = [ext.majorOpcode, 32, 3+trapList.length, pic, offX, offY]; for (var i=0; i < trapList.length; i++) @@ -381,11 +386,11 @@ exports.requireExt = function(display, callback) } X.pack_stream.pack(format, params); X.pack_stream.flush(); + X.seq_num++; }; ext.Triangles = function(op, src, srcX, srcY, dst, maskFormat, tris) { - X.seq_num++; var format = 'CCSCxxxLLLss'; var params = [ext.majorOpcode, 11, 6+tris.length, op, src, dst, maskFormat, srcX, srcY]; for (var i=0; i < tris.length; i+=6) @@ -401,28 +406,28 @@ exports.requireExt = function(display, callback) } X.pack_stream.pack(format, params); X.pack_stream.flush(); + X.seq_num++; } ext.CreateGlyphSet = function(gsid, format) { - X.seq_num++; X.pack_stream.pack('CCSLL', [ext.majorOpcode, 17, 3, gsid, format]); X.pack_stream.flush(); + X.seq_num++; } ext.ReferenceGlyphSet = function(gsid, existing) { - X.seq_num++; X.pack_stream.pack('CCSLL', [ext.majorOpcode, 18, 3, gsid, existing]); X.pack_stream.flush(); + X.seq_num++; } ext.FreeGlyphSet = function(gsid) { - X.seq_num++; X.pack_stream.pack('CCSL', [ext.majorOpcode, 19, 2, gsid]); X.pack_stream.flush(); + X.seq_num++; } ext.AddGlyphs = function(gsid, glyphs) { - X.seq_num++; var numGlyphs = glyphs.length; var imageBytes = 0; var glyphPaddedLength; @@ -466,6 +471,7 @@ exports.requireExt = function(display, callback) X.pack_stream.write_queue.push(glyphs[i].image); } X.pack_stream.flush(); + X.seq_num++; } //AddGlyphsFromPicture, opcode=21 (not in spec) @@ -513,7 +519,6 @@ exports.requireExt = function(display, callback) var opcode = compositeGlyphsOpcodeFromBits[glyphBits]; var charFormat = formatFromBits[glyphBits]; var charLength = glyphBits / 8; - X.seq_num++; var length = 7; var glyphs_length_split = []; for (var i=0; i < glyphs.length; ++i) { @@ -549,6 +554,7 @@ exports.requireExt = function(display, callback) } } X.pack_stream.flush(); + X.seq_num++; }; ext.CompositeGlyphs8 = function(op, src, dst, maskFormat, gsid, srcX, srcY, glyphs) From 21cc95a8bb3a3f2c9471b6a5e8d82e7246086660 Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Sun, 8 Nov 2015 16:51:34 +1100 Subject: [PATCH 08/12] add test to verify all ext files are at least parseable --- test/smoke-require-ext.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 test/smoke-require-ext.js diff --git a/test/smoke-require-ext.js b/test/smoke-require-ext.js new file mode 100644 index 0000000..ef8233e --- /dev/null +++ b/test/smoke-require-ext.js @@ -0,0 +1,16 @@ +var fs = require('fs'); +var assert = require('assert'); + +describe('all extension modules', function() { + it('should not throw when require\'d', function(done) { + var extFolder = __dirname + '/../lib/ext'; + fs.readdir(extFolder, function(err, list) { + assert.ifError(err); + list.forEach(function(name) { + var m = require(extFolder + '/' + name); + }); + done(); + }); + } +}) + From 4a3f3f607534ed09106da868065cd071769eac5f Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Sun, 8 Nov 2015 16:53:24 +1100 Subject: [PATCH 09/12] fix formatting; fix binomial filter params check; set format beforehand for SetPictureTransform --- lib/ext/render.js | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/lib/ext/render.js b/lib/ext/render.js index ff3b9e0..b711edc 100644 --- a/lib/ext/render.js +++ b/lib/ext/render.js @@ -170,12 +170,11 @@ exports.requireExt = function(display, callback) } ext.SetPictureTransform = function(pid, matrix) { - var format = 'CCSL'; + var format = 'CCSLLLLLLLLLLLLL'; if (matrix.length !== 9) throw 'Render.SetPictureTransform: incorrect transform matrix. Must be array of 9 numbers'; var params = [ext.majorOpcode, 28, 11, pid]; for (var i=0; i < 9; ++i) { - format += 'L'; if (typeof matrix[i] !== 'number') throw 'Render.SetPictureTransform: matrix element must be a number'; params.push(floatToFix(matrix[i])); @@ -201,7 +200,7 @@ exports.requireExt = function(display, callback) reqLen += xutil.padded_length(name.length+3)/4 + filterParams.length; if (name == 'nearest' || name == 'bilinear' || name == 'fast' || name == 'good' || name == 'best') { - if (filterParams.length != 0) { + if (filterParams.length !== 0) { throw 'Render.SetPictureFilter: "' + name + '" - unexpected parameters for filters'; } } else if (name == 'convolution') { @@ -213,7 +212,7 @@ exports.requireExt = function(display, callback) params.push(floatToFix(filterParams[i])); } } else if (name == 'binomial' || name == 'gaussian') { - if (filterParams.length < 2) { + if (filterParams.length !== 1) { throw 'Render.SetPictureFilter: "' + name + '" - incorrect number of parameters, must be exactly 1 number, instead got: ' + filterParams; } format += 'L'; @@ -674,23 +673,23 @@ exports.requireExt = function(display, callback) /*, * Operators only available in version 0.11, */ - BlendMinimum: 0x30, - Multiply: 0x30, - Screen: 0x31, - Overlay: 0x32, - Darken: 0x33, - Lighten: 0x34, - ColorDodge: 0x35, - ColorBurn: 0x36, - HardLight: 0x37, - SoftLight: 0x38, - Difference: 0x39, - Exclusion: 0x3a, - HSLHue: 0x3b, + BlendMinimum : 0x30, + Multiply : 0x30, + Screen : 0x31, + Overlay : 0x32, + Darken : 0x33, + Lighten : 0x34, + ColorDodge : 0x35, + ColorBurn : 0x36, + HardLight : 0x37, + SoftLight : 0x38, + Difference : 0x39, + Exclusion : 0x3a, + HSLHue : 0x3b, HSLSaturation: 0x3c, - HSLColor: 0x3d, + HSLColor : 0x3d, HSLLuminosity: 0x3e, - BlendMaximum: 0x3e + BlendMaximum : 0x3e }; ext.PolyEdge = { @@ -714,7 +713,7 @@ exports.requireExt = function(display, callback) Unknown: 0, HorizontalRGB: 1, HorizontalBGR: 2, - VerticalRGB : 3, + VerticalRGB : 3, VerticalBGR : 4, None : 5 }; From 737ecc7b6016ba1a5a9f2d8eed3941931918f31a Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Sun, 8 Nov 2015 16:56:16 +1100 Subject: [PATCH 10/12] build: add node 0.12, 4.2 and 5.0 to matrix --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3218f2b..58649b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,7 @@ env: language: node_js node_js: - - 0.10 + - '0.10' + - '0.12' + - '4.2' + - '5.0' From c473fe4f72b7d695bfdfa716d40f4d743766593a Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Sun, 8 Nov 2015 16:57:21 +1100 Subject: [PATCH 11/12] fix closing '})' --- test/smoke-require-ext.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/smoke-require-ext.js b/test/smoke-require-ext.js index ef8233e..5ce9d58 100644 --- a/test/smoke-require-ext.js +++ b/test/smoke-require-ext.js @@ -11,6 +11,6 @@ describe('all extension modules', function() { }); done(); }); - } + }); }) From b635b3209d8b453115799b7fde850218fea133bb Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Sun, 8 Nov 2015 23:59:10 +1100 Subject: [PATCH 12/12] increment seq_num before assigning callback so response mapping is correct --- lib/ext/render.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ext/render.js b/lib/ext/render.js index b711edc..b609c29 100644 --- a/lib/ext/render.js +++ b/lib/ext/render.js @@ -33,6 +33,7 @@ exports.requireExt = function(display, callback) ext.QueryPictFormat = function(callback) { X.pack_stream.pack('CCS', [ext.majorOpcode, 1, 1]); + X.seq_num++; X.replies[X.seq_num] = [ function (buf, opt) { var res = {}; @@ -57,12 +58,12 @@ exports.requireExt = function(display, callback) callback ]; X.pack_stream.flush(); - X.seq_num++; } ext.QueryFilters = function(callback) { X.pack_stream.pack('CCSL', [ext.majorOpcode, 29, 2, display.screen[0].root]); + X.seq_num++; X.replies[X.seq_num] = [ function(buf, opt) { var h = buf.unpack('LL'); @@ -89,7 +90,6 @@ exports.requireExt = function(display, callback) callback ]; X.pack_stream.flush(); - X.seq_num++; } var valueList = [