From 149b3af105bd493cf267a1b69a3661cdfa88a46c Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 7 Nov 2013 13:54:54 +0100 Subject: [PATCH] broadway: Use zlib compression for broadway buffers This imports the MIT licensed js unzip from: https://github.com/imaya/zlib.js and uses it to decompress in js on the client side. --- gdk/broadway/Makefile.am | 6 ++--- gdk/broadway/broadway-output.c | 43 +++++++++++++++++++--------------- gdk/broadway/broadway.js | 5 ++-- gdk/broadway/rawinflate.min.js | 15 ++++++++++++ gdk/broadway/toarray.pl | 24 ++++++++++--------- 5 files changed, 58 insertions(+), 35 deletions(-) create mode 100644 gdk/broadway/rawinflate.min.js diff --git a/gdk/broadway/Makefile.am b/gdk/broadway/Makefile.am index e48e09eaab..d0bcabd539 100644 --- a/gdk/broadway/Makefile.am +++ b/gdk/broadway/Makefile.am @@ -30,12 +30,12 @@ libgdkbroadwayinclude_HEADERS = \ gdkbroadwayvisual.h clienthtml.h: client.html - $(PERL) $(srcdir)/toarray.pl $(srcdir)/client.html client_html > $@ + $(PERL) $(srcdir)/toarray.pl client_html $(srcdir)/client.html > $@ EXTRA_DIST += client.html -broadwayjs.h: broadway.js - $(PERL) $(srcdir)/toarray.pl $(srcdir)/broadway.js broadway_js > $@ +broadwayjs.h: broadway.js rawinflate.min.js + $(PERL) $(srcdir)/toarray.pl broadway_js $(srcdir)/broadway.js $(srcdir)/rawinflate.min.js > $@ EXTRA_DIST += broadway.js diff --git a/gdk/broadway/broadway-output.c b/gdk/broadway/broadway-output.c index 517a65b35f..e77be3355b 100644 --- a/gdk/broadway/broadway-output.c +++ b/gdk/broadway/broadway-output.c @@ -154,18 +154,6 @@ append_uint32 (BroadwayOutput *output, guint32 v) buf[3] = (v >> 24) & 0xff; } -static void -overwrite_uint32 (BroadwayOutput *output, gsize pos, guint32 v) -{ - guint8 *buf = (guint8 *)output->buf->str + pos; - - buf[0] = (v >> 0) & 0xff; - buf[1] = (v >> 8) & 0xff; - buf[2] = (v >> 16) & 0xff; - buf[3] = (v >> 24) & 0xff; -} - - static void write_header(BroadwayOutput *output, char op) { @@ -283,8 +271,11 @@ broadway_output_put_buffer (BroadwayOutput *output, BroadwayBuffer *prev_buffer, BroadwayBuffer *buffer) { - gsize size_start, image_start, len; + gsize len; int w, h; + GZlibCompressor *compressor; + GOutputStream *out, *out_mem; + GString *encoded; write_header (output, BROADWAY_OP_PUT_BUFFER); @@ -295,12 +286,26 @@ broadway_output_put_buffer (BroadwayOutput *output, append_uint16 (output, w); append_uint16 (output, h); - size_start = output->buf->len; - append_uint32 (output, 0); + encoded = g_string_new (""); + broadway_buffer_encode (buffer, prev_buffer, encoded); - image_start = output->buf->len; - broadway_buffer_encode (buffer, prev_buffer, output->buf); - len = output->buf->len - image_start; + compressor = g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW, -1); + out_mem = g_memory_output_stream_new_resizable (); + out = g_converter_output_stream_new (out_mem, G_CONVERTER (compressor)); + g_object_unref (compressor); - overwrite_uint32 (output, size_start, len); + if (!g_output_stream_write_all (out, encoded->str, encoded->len, + NULL, NULL, NULL) || + !g_output_stream_close (out, NULL, NULL)) + g_warning ("compression failed\n"); + + + len = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (out_mem)); + append_uint32 (output, len); + + g_string_append_len (output->buf, g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (out_mem)), len); + + g_string_free (encoded, TRUE); + g_object_unref (out); + g_object_unref (out_mem); } diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js index 084cce76db..90e7eb09c7 100644 --- a/gdk/broadway/broadway.js +++ b/gdk/broadway/broadway.js @@ -329,7 +329,7 @@ function copyRect(src, srcX, srcY, dest, destX, destY, width, height) } } -function cmdPutBuffer(id, w, h, data) +function cmdPutBuffer(id, w, h, compressed) { var surface = surfaces[id]; var context = surface.canvas.getContext("2d"); @@ -345,7 +345,8 @@ function cmdPutBuffer(id, w, h, data) var src = 0; var dest = 0; - //log("put buffer " + w + "x" + h + " size: " + data.length); + var inflate = new Zlib.RawInflate(compressed); + var data = inflate.decompress(); while (src < data.length) { var b = data[src++]; diff --git a/gdk/broadway/rawinflate.min.js b/gdk/broadway/rawinflate.min.js new file mode 100644 index 0000000000..f9c7f87ecd --- /dev/null +++ b/gdk/broadway/rawinflate.min.js @@ -0,0 +1,15 @@ +/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var l=void 0,p=this;function q(c,d){var a=c.split("."),b=p;!(a[0]in b)&&b.execScript&&b.execScript("var "+a[0]);for(var e;a.length&&(e=a.shift());)!a.length&&d!==l?b[e]=d:b=b[e]?b[e]:b[e]={}};var r="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array;function u(c){var d=c.length,a=0,b=Number.POSITIVE_INFINITY,e,f,g,h,k,m,s,n,t;for(n=0;na&&(a=c[n]),c[n]>=1;for(t=m;t>>=1;switch(c){case 0:var d=this.input,a=this.d,b=this.b,e=this.a,f=l,g=l,h=l,k=b.length,m=l;this.c=this.f=0;f=d[a++];if(f===l)throw Error("invalid uncompressed block header: LEN (first byte)");g=f;f=d[a++];if(f===l)throw Error("invalid uncompressed block header: LEN (second byte)");g|=f<<8;f=d[a++];if(f===l)throw Error("invalid uncompressed block header: NLEN (first byte)");h=f;f=d[a++];if(f===l)throw Error("invalid uncompressed block header: NLEN (second byte)");h|= +f<<8;if(g===~h)throw Error("invalid uncompressed block header: length verify");if(a+g>d.length)throw Error("input buffer is broken");switch(this.i){case x:for(;e+g>b.length;){m=k-e;g-=m;if(r)b.set(d.subarray(a,a+m),e),e+=m,a+=m;else for(;m--;)b[e++]=d[a++];this.a=e;b=this.e();e=this.a}break;case w:for(;e+g>b.length;)b=this.e({o:2});break;default:throw Error("invalid inflate mode");}if(r)b.set(d.subarray(a,a+g),e),e+=g,a+=g;else for(;g--;)b[e++]=d[a++];this.d=a;this.a=e;this.b=b;break;case 1:this.j(z, +A);break;case 2:B(this);break;default:throw Error("unknown BTYPE: "+c);}}return this.m()}; +var C=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],D=r?new Uint16Array(C):C,E=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],F=r?new Uint16Array(E):E,G=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],H=r?new Uint8Array(G):G,I=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],J=r?new Uint16Array(I):I,K=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13, +13],L=r?new Uint8Array(K):K,M=new (r?Uint8Array:Array)(288),N,O;N=0;for(O=M.length;N=N?8:255>=N?9:279>=N?7:8;var z=u(M),P=new (r?Uint8Array:Array)(30),Q,R;Q=0;for(R=P.length;Q>>d;c.c=b-d;c.d=f;return g} +function S(c,d){for(var a=c.f,b=c.c,e=c.input,f=c.d,g=d[0],h=d[1],k,m,s;b>>16;c.f=a>>s;c.c=b-s;c.d=f;return m&65535} +function B(c){function d(a,c,b){var d,f,e,g;for(g=0;gf)b>=e&&(this.a=b,a=this.e(),b=this.a),a[b++]=f;else{g=f-257;k=F[g];0=e&&(this.a=b,a=this.e(),b=this.a);for(;k--;)a[b]=a[b++-h]}for(;8<=this.c;)this.c-=8,this.d--;this.a=b}; +v.prototype.s=function(c,d){var a=this.b,b=this.a;this.n=c;for(var e=a.length,f,g,h,k;256!==(f=S(this,c));)if(256>f)b>=e&&(a=this.e(),e=a.length),a[b++]=f;else{g=f-257;k=F[g];0e&&(a=this.e(),e=a.length);for(;k--;)a[b]=a[b++-h]}for(;8<=this.c;)this.c-=8,this.d--;this.a=b}; +v.prototype.e=function(){var c=new (r?Uint8Array:Array)(this.a-32768),d=this.a-32768,a,b,e=this.b;if(r)c.set(e.subarray(32768,c.length));else{a=0;for(b=c.length;aa;++a)e[a]=e[d+a];this.a=32768;return e}; +v.prototype.u=function(c){var d,a=this.input.length/this.d+1|0,b,e,f,g=this.input,h=this.b;c&&("number"===typeof c.o&&(a=c.o),"number"===typeof c.q&&(a+=c.q));2>a?(b=(g.length-this.d)/this.n[2],f=258*(b/2)|0,e=fd&&(this.b.length=d),c=this.b);return this.buffer=c};q("Zlib.RawInflate",v);q("Zlib.RawInflate.prototype.decompress",v.prototype.t);var T={ADAPTIVE:w,BLOCK:x},U,V,W,X;if(Object.keys)U=Object.keys(T);else for(V in U=[],W=0,T)U[W++]=V;W=0;for(X=U.length;W) { + foreach my $c (split //, $line) { + printf ("\\x%02x", ord ($c)); + } + } } -print ";\n"; + +print "\";\n"; +