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.
This commit is contained in:
Alexander Larsson 2013-11-07 13:54:54 +01:00
parent 5ef114ba42
commit 149b3af105
5 changed files with 58 additions and 35 deletions

View File

@ -30,12 +30,12 @@ libgdkbroadwayinclude_HEADERS = \
gdkbroadwayvisual.h gdkbroadwayvisual.h
clienthtml.h: client.html 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 EXTRA_DIST += client.html
broadwayjs.h: broadway.js broadwayjs.h: broadway.js rawinflate.min.js
$(PERL) $(srcdir)/toarray.pl $(srcdir)/broadway.js broadway_js > $@ $(PERL) $(srcdir)/toarray.pl broadway_js $(srcdir)/broadway.js $(srcdir)/rawinflate.min.js > $@
EXTRA_DIST += broadway.js EXTRA_DIST += broadway.js

View File

@ -154,18 +154,6 @@ append_uint32 (BroadwayOutput *output, guint32 v)
buf[3] = (v >> 24) & 0xff; 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 static void
write_header(BroadwayOutput *output, char op) write_header(BroadwayOutput *output, char op)
{ {
@ -283,8 +271,11 @@ broadway_output_put_buffer (BroadwayOutput *output,
BroadwayBuffer *prev_buffer, BroadwayBuffer *prev_buffer,
BroadwayBuffer *buffer) BroadwayBuffer *buffer)
{ {
gsize size_start, image_start, len; gsize len;
int w, h; int w, h;
GZlibCompressor *compressor;
GOutputStream *out, *out_mem;
GString *encoded;
write_header (output, BROADWAY_OP_PUT_BUFFER); write_header (output, BROADWAY_OP_PUT_BUFFER);
@ -295,12 +286,26 @@ broadway_output_put_buffer (BroadwayOutput *output,
append_uint16 (output, w); append_uint16 (output, w);
append_uint16 (output, h); append_uint16 (output, h);
size_start = output->buf->len; encoded = g_string_new ("");
append_uint32 (output, 0); broadway_buffer_encode (buffer, prev_buffer, encoded);
image_start = output->buf->len; compressor = g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW, -1);
broadway_buffer_encode (buffer, prev_buffer, output->buf); out_mem = g_memory_output_stream_new_resizable ();
len = output->buf->len - image_start; 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);
} }

View File

@ -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 surface = surfaces[id];
var context = surface.canvas.getContext("2d"); var context = surface.canvas.getContext("2d");
@ -345,7 +345,8 @@ function cmdPutBuffer(id, w, h, data)
var src = 0; var src = 0;
var dest = 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) { while (src < data.length) {
var b = data[src++]; var b = data[src++];

15
gdk/broadway/rawinflate.min.js vendored Normal file
View File

@ -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;n<d;++n)c[n]>a&&(a=c[n]),c[n]<b&&(b=c[n]);e=1<<a;f=new (r?Uint32Array:Array)(e);g=1;h=0;for(k=2;g<=a;){for(n=0;n<d;++n)if(c[n]===g){m=0;s=h;for(t=0;t<g;++t)m=m<<1|s&1,s>>=1;for(t=m;t<e;t+=k)f[t]=g<<16|n;++h}++g;h<<=1;k<<=1}return[f,a,b]};function v(c,d){this.g=[];this.h=32768;this.c=this.f=this.d=this.k=0;this.input=r?new Uint8Array(c):c;this.l=!1;this.i=w;this.p=!1;if(d||!(d={}))d.index&&(this.d=d.index),d.bufferSize&&(this.h=d.bufferSize),d.bufferType&&(this.i=d.bufferType),d.resize&&(this.p=d.resize);switch(this.i){case x:this.a=32768;this.b=new (r?Uint8Array:Array)(32768+this.h+258);break;case w:this.a=0;this.b=new (r?Uint8Array:Array)(this.h);this.e=this.u;this.m=this.r;this.j=this.s;break;default:throw Error("invalid inflate mode");
}}var x=0,w=1;
v.prototype.t=function(){for(;!this.l;){var c=y(this,3);c&1&&(this.l=!0);c>>>=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<O;++N)M[N]=143>=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<R;++Q)P[Q]=5;var A=u(P);function y(c,d){for(var a=c.f,b=c.c,e=c.input,f=c.d,g;b<d;){g=e[f++];if(g===l)throw Error("input buffer is broken");a|=g<<b;b+=8}g=a&(1<<d)-1;c.f=a>>>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<h;){k=e[f++];if(k===l)break;a|=k<<b;b+=8}m=g[a&(1<<h)-1];s=m>>>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;g<a;)switch(d=S(this,c),d){case 16:for(e=3+y(this,2);e--;)b[g++]=f;break;case 17:for(e=3+y(this,3);e--;)b[g++]=0;f=0;break;case 18:for(e=11+y(this,7);e--;)b[g++]=0;f=0;break;default:f=b[g++]=d}return b}var a=y(c,5)+257,b=y(c,5)+1,e=y(c,4)+4,f=new (r?Uint8Array:Array)(D.length),g,h,k,m;for(m=0;m<e;++m)f[D[m]]=y(c,3);g=u(f);h=new (r?Uint8Array:Array)(a);k=new (r?Uint8Array:Array)(b);c.j(u(d.call(c,a,g,h)),u(d.call(c,b,g,k)))}
v.prototype.j=function(c,d){var a=this.b,b=this.a;this.n=c;for(var e=a.length-258,f,g,h,k;256!==(f=S(this,c));)if(256>f)b>=e&&(this.a=b,a=this.e(),b=this.a),a[b++]=f;else{g=f-257;k=F[g];0<H[g]&&(k+=y(this,H[g]));f=S(this,d);h=J[f];0<L[f]&&(h+=y(this,L[f]));b>=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];0<H[g]&&(k+=y(this,H[g]));f=S(this,d);h=J[f];0<L[f]&&(h+=y(this,L[f]));b+k>e&&(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;a<b;++a)c[a]=e[a+32768]}this.g.push(c);this.k+=c.length;if(r)e.set(e.subarray(d,d+32768));else for(a=0;32768>a;++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=f<h.length?h.length+f:h.length<<1):e=h.length*a;r?(d=new Uint8Array(e),d.set(h)):d=h;return this.b=d};
v.prototype.m=function(){var c=0,d=this.b,a=this.g,b,e=new (r?Uint8Array:Array)(this.k+(this.a-32768)),f,g,h,k;if(0===a.length)return r?this.b.subarray(32768,this.a):this.b.slice(32768,this.a);f=0;for(g=a.length;f<g;++f){b=a[f];h=0;for(k=b.length;h<k;++h)e[c++]=b[h]}f=32768;for(g=this.a;f<g;++f)e[c++]=d[f];this.g=[];return this.buffer=e};
v.prototype.r=function(){var c,d=this.a;r?this.p?(c=new Uint8Array(d),c.set(this.b.subarray(0,d))):c=this.b.subarray(0,d):(this.b.length>d&&(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<X;++W)V=U[W],q("Zlib.RawInflate.BufferType."+V,T[V]);}).call(this); //@ sourceMappingURL=rawinflate.min.js.map

View File

@ -1,15 +1,17 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
my $FILENAME = $ARGV[0]; my $ARRAYNAME = $ARGV[0];
print "static const char $ARRAYNAME\[\] = \"";
open FILE, $FILENAME or die "Cannot open $FILENAME"; for ($i = 1; $i <= $#ARGV; $i = $i + 1) {
my $FILENAME = $ARGV[$i];
my $ARRAYNAME = $ARGV[1]; open FILE, $FILENAME or die "Cannot open $FILENAME";
print "static const char $ARRAYNAME\[\] ="; while (my $line = <FILE>) {
while (<FILE>) { foreach my $c (split //, $line) {
s@\\@\\\\@g; printf ("\\x%02x", ord ($c));
s@"@\\"@g; }
chomp ($_); }
print "\n \"$_\\n\"";
} }
print ";\n";
print "\";\n";