deb-spice-html5/spicetype.js

474 lines
12 KiB
JavaScript

"use strict";
/*
Copyright (C) 2012 by Jeremy P. White <jwhite@codeweavers.com>
This file is part of spice-html5.
spice-html5 is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
spice-html5 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with spice-html5. If not, see <http://www.gnu.org/licenses/>.
*/
/*----------------------------------------------------------------------------
** Spice types
** This file contains classes for common spice types.
** Generally, they are used as helpers in reading and writing messages
** to and from the server.
**--------------------------------------------------------------------------*/
function SpiceChannelId()
{
}
SpiceChannelId.prototype =
{
from_dv: function(dv, at, mb)
{
this.type = dv.getUint8(at, true); at ++;
this.id = dv.getUint8(at, true); at ++;
return at;
},
}
function SpiceRect()
{
}
SpiceRect.prototype =
{
from_dv: function(dv, at, mb)
{
this.top = dv.getUint32(at, true); at += 4;
this.left = dv.getUint32(at, true); at += 4;
this.bottom = dv.getUint32(at, true); at += 4;
this.right = dv.getUint32(at, true); at += 4;
return at;
},
is_same_size : function(r)
{
if ((this.bottom - this.top) == (r.bottom - r.top) &&
(this.right - this.left) == (r.right - r.left) )
return true;
return false;
},
}
function SpiceClipRects()
{
}
SpiceClipRects.prototype =
{
from_dv: function(dv, at, mb)
{
var i;
this.num_rects = dv.getUint32(at, true); at += 4;
if (this.num_rects > 0)
this.rects = [];
for (i = 0; i < this.num_rects; i++)
{
this.rects[i] = new SpiceRect();
at = this.rects[i].from_dv(dv, at, mb);
}
return at;
},
}
function SpiceClip()
{
}
SpiceClip.prototype =
{
from_dv: function(dv, at, mb)
{
this.type = dv.getUint8(at, true); at ++;
if (this.type == SPICE_CLIP_TYPE_RECTS)
{
this.rects = new SpiceClipRects();
at = this.rects.from_dv(dv, at, mb);
}
return at;
},
}
function SpiceImageDescriptor()
{
}
SpiceImageDescriptor.prototype =
{
from_dv: function(dv, at, mb)
{
this.id = dv.getUint64(at, true); at += 8;
this.type = dv.getUint8(at, true); at ++;
this.flags = dv.getUint8(at, true); at ++;
this.width = dv.getUint32(at, true); at += 4;
this.height= dv.getUint32(at, true); at += 4;
return at;
},
}
function SpicePalette()
{
}
SpicePalette.prototype =
{
from_dv: function(dv, at, mb)
{
var i;
this.unique = dv.getUint64(at, true); at += 8;
this.num_ents = dv.getUint16(at, true); at += 2;
this.ents = [];
for (i = 0; i < this.num_ents; i++)
{
this.ents[i] = dv.getUint32(at, true); at += 4;
}
return at;
},
}
function SpiceBitmap()
{
}
SpiceBitmap.prototype =
{
from_dv: function(dv, at, mb)
{
this.format = dv.getUint8(at, true); at++;
this.flags = dv.getUint8(at, true); at++;
this.x = dv.getUint32(at, true); at += 4;
this.y = dv.getUint32(at, true); at += 4;
this.stride = dv.getUint32(at, true); at += 4;
if (this.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)
{
this.palette_id = dv.getUint64(at, true); at += 8;
}
else
{
var offset = dv.getUint32(at, true); at += 4;
if (offset == 0)
this.palette = null;
else
{
this.palette = new SpicePalette;
this.palette.from_dv(dv, offset, mb);
}
}
// FIXME - should probably constrain this to the offset
// of palette, if non zero
this.data = mb.slice(at);
at += this.data.byteLength;
return at;
},
}
function SpiceImage()
{
}
SpiceImage.prototype =
{
from_dv: function(dv, at, mb)
{
this.descriptor = new SpiceImageDescriptor;
at = this.descriptor.from_dv(dv, at, mb);
if (this.descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB)
{
this.lz_rgb = new Object();
this.lz_rgb.length = dv.getUint32(at, true); at += 4;
var initial_at = at;
this.lz_rgb.magic = "";
for (var i = 3; i >= 0; i--)
this.lz_rgb.magic += String.fromCharCode(dv.getUint8(at + i));
at += 4;
// NOTE: The endian change is *correct*
this.lz_rgb.version = dv.getUint32(at); at += 4;
this.lz_rgb.type = dv.getUint32(at); at += 4;
this.lz_rgb.width = dv.getUint32(at); at += 4;
this.lz_rgb.height = dv.getUint32(at); at += 4;
this.lz_rgb.stride = dv.getUint32(at); at += 4;
this.lz_rgb.top_down = dv.getUint32(at); at += 4;
var header_size = at - initial_at;
this.lz_rgb.data = mb.slice(at, this.lz_rgb.length + at - header_size);
at += this.lz_rgb.data.byteLength;
}
if (this.descriptor.type == SPICE_IMAGE_TYPE_BITMAP)
{
this.bitmap = new SpiceBitmap;
at = this.bitmap.from_dv(dv, at, mb);
}
if (this.descriptor.type == SPICE_IMAGE_TYPE_SURFACE)
{
this.surface_id = dv.getUint32(at, true); at += 4;
}
if (this.descriptor.type == SPICE_IMAGE_TYPE_JPEG)
{
this.jpeg = new Object;
this.jpeg.data_size = dv.getUint32(at, true); at += 4;
this.jpeg.data = mb.slice(at);
at += this.jpeg.data.byteLength;
}
if (this.descriptor.type == SPICE_IMAGE_TYPE_JPEG_ALPHA)
{
this.jpeg_alpha = new Object;
this.jpeg_alpha.flags = dv.getUint8(at, true); at += 1;
this.jpeg_alpha.jpeg_size = dv.getUint32(at, true); at += 4;
this.jpeg_alpha.data_size = dv.getUint32(at, true); at += 4;
this.jpeg_alpha.data = mb.slice(at, this.jpeg_alpha.jpeg_size + at);
at += this.jpeg_alpha.data.byteLength;
// Alpha channel is an LZ image
this.jpeg_alpha.alpha = new Object();
this.jpeg_alpha.alpha.length = this.jpeg_alpha.data_size - this.jpeg_alpha.jpeg_size;
var initial_at = at;
this.jpeg_alpha.alpha.magic = "";
for (var i = 3; i >= 0; i--)
this.jpeg_alpha.alpha.magic += String.fromCharCode(dv.getUint8(at + i));
at += 4;
// NOTE: The endian change is *correct*
this.jpeg_alpha.alpha.version = dv.getUint32(at); at += 4;
this.jpeg_alpha.alpha.type = dv.getUint32(at); at += 4;
this.jpeg_alpha.alpha.width = dv.getUint32(at); at += 4;
this.jpeg_alpha.alpha.height = dv.getUint32(at); at += 4;
this.jpeg_alpha.alpha.stride = dv.getUint32(at); at += 4;
this.jpeg_alpha.alpha.top_down = dv.getUint32(at); at += 4;
var header_size = at - initial_at;
this.jpeg_alpha.alpha.data = mb.slice(at, this.jpeg_alpha.alpha.length + at - header_size);
at += this.jpeg_alpha.alpha.data.byteLength;
}
if (this.descriptor.type == SPICE_IMAGE_TYPE_QUIC)
{
this.quic = new SpiceQuic;
at = this.quic.from_dv(dv, at, mb);
}
return at;
},
}
function SpiceQMask()
{
}
SpiceQMask.prototype =
{
from_dv: function(dv, at, mb)
{
this.flags = dv.getUint8(at, true); at++;
this.pos = new SpicePoint;
at = this.pos.from_dv(dv, at, mb);
var offset = dv.getUint32(at, true); at += 4;
if (offset == 0)
{
this.bitmap = null;
return at;
}
this.bitmap = new SpiceImage;
return this.bitmap.from_dv(dv, offset, mb);
},
}
function SpicePattern()
{
}
SpicePattern.prototype =
{
from_dv: function(dv, at, mb)
{
var offset = dv.getUint32(at, true); at += 4;
if (offset == 0)
{
this.pat = null;
}
else
{
this.pat = new SpiceImage;
this.pat.from_dv(dv, offset, mb);
}
this.pos = new SpicePoint;
return this.pos.from_dv(dv, at, mb);
}
}
function SpiceBrush()
{
}
SpiceBrush.prototype =
{
from_dv: function(dv, at, mb)
{
this.type = dv.getUint8(at, true); at ++;
if (this.type == SPICE_BRUSH_TYPE_SOLID)
{
this.color = dv.getUint32(at, true); at += 4;
}
else if (this.type == SPICE_BRUSH_TYPE_PATTERN)
{
this.pattern = new SpicePattern;
at = this.pattern.from_dv(dv, at, mb);
}
return at;
},
}
function SpiceFill()
{
}
SpiceFill.prototype =
{
from_dv: function(dv, at, mb)
{
this.brush = new SpiceBrush;
at = this.brush.from_dv(dv, at, mb);
this.rop_descriptor = dv.getUint16(at, true); at += 2;
this.mask = new SpiceQMask;
return this.mask.from_dv(dv, at, mb);
},
}
function SpiceCopy()
{
}
SpiceCopy.prototype =
{
from_dv: function(dv, at, mb)
{
var offset = dv.getUint32(at, true); at += 4;
if (offset == 0)
{
this.src_bitmap = null;
}
else
{
this.src_bitmap = new SpiceImage;
this.src_bitmap.from_dv(dv, offset, mb);
}
this.src_area = new SpiceRect;
at = this.src_area.from_dv(dv, at, mb);
this.rop_descriptor = dv.getUint16(at, true); at += 2;
this.scale_mode = dv.getUint8(at, true); at ++;
this.mask = new SpiceQMask;
return this.mask.from_dv(dv, at, mb);
},
}
function SpicePoint16()
{
}
SpicePoint16.prototype =
{
from_dv: function(dv, at, mb)
{
this.x = dv.getUint16(at, true); at += 2;
this.y = dv.getUint16(at, true); at += 2;
return at;
},
}
function SpicePoint()
{
}
SpicePoint.prototype =
{
from_dv: function(dv, at, mb)
{
this.x = dv.getUint32(at, true); at += 4;
this.y = dv.getUint32(at, true); at += 4;
return at;
},
}
function SpiceCursorHeader()
{
}
SpiceCursorHeader.prototype =
{
from_dv: function(dv, at, mb)
{
this.unique = dv.getUint64(at, true); at += 8;
this.type = dv.getUint8(at, true); at ++;
this.width = dv.getUint16(at, true); at += 2;
this.height = dv.getUint16(at, true); at += 2;
this.hot_spot_x = dv.getUint16(at, true); at += 2;
this.hot_spot_y = dv.getUint16(at, true); at += 2;
return at;
},
}
function SpiceCursor()
{
}
SpiceCursor.prototype =
{
from_dv: function(dv, at, mb)
{
this.flags = dv.getUint16(at, true); at += 2;
if (this.flags & SPICE_CURSOR_FLAGS_NONE)
this.header = null;
else
{
this.header = new SpiceCursorHeader;
at = this.header.from_dv(dv, at, mb);
this.data = mb.slice(at);
at += this.data.byteLength;
}
return at;
},
}
function SpiceSurface()
{
}
SpiceSurface.prototype =
{
from_dv: function(dv, at, mb)
{
this.surface_id = dv.getUint32(at, true); at += 4;
this.width = dv.getUint32(at, true); at += 4;
this.height = dv.getUint32(at, true); at += 4;
this.format = dv.getUint32(at, true); at += 4;
this.flags = dv.getUint32(at, true); at += 4;
return at;
},
}
/* FIXME - SpiceImage types lz_plt, jpeg, zlib_glz, and jpeg_alpha are
completely unimplemented */