mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
Implemented remaining operations as possible.
This commit is contained in:
@@ -300,6 +300,68 @@ Guacamole.Layer = function(width, height) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task within the current layer just as scheduleTast() does,
|
||||||
|
* except that another specified layer will be blocked until this task
|
||||||
|
* completes, and this task will not start until the other layer is
|
||||||
|
* ready.
|
||||||
|
*
|
||||||
|
* Essentially, a task is scheduled in both layers, and the specified task
|
||||||
|
* will only be performed once both layers are ready, and neither layer may
|
||||||
|
* proceed until this task completes.
|
||||||
|
*
|
||||||
|
* Note that there is no way to specify whether the task starts blocked,
|
||||||
|
* as whether the task is blocked depends completely on whether the
|
||||||
|
* other layer is currently ready.
|
||||||
|
*
|
||||||
|
* @param {Guacamole.Layer} otherLayer The other layer which must be blocked
|
||||||
|
* until this task completes.
|
||||||
|
* @param {function} handler The function to call when possible.
|
||||||
|
*/
|
||||||
|
function scheduleTaskSynced(otherLayer, handler) {
|
||||||
|
|
||||||
|
// If we ARE the other layer, no need to sync.
|
||||||
|
// Syncing would result in deadlock.
|
||||||
|
if (layer === otherLayer)
|
||||||
|
scheduleTask(handler);
|
||||||
|
|
||||||
|
// Otherwise synchronize operation with other layer
|
||||||
|
else {
|
||||||
|
|
||||||
|
var drawComplete = false;
|
||||||
|
var layerLock = null;
|
||||||
|
|
||||||
|
function performTask() {
|
||||||
|
|
||||||
|
// Perform task
|
||||||
|
handler();
|
||||||
|
|
||||||
|
// Unblock the other layer now that draw is complete
|
||||||
|
if (layerLock != null)
|
||||||
|
layerLock.unblock();
|
||||||
|
|
||||||
|
// Flag operation as done
|
||||||
|
drawComplete = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently blocked draw task
|
||||||
|
var task = scheduleTask(performTask, true);
|
||||||
|
|
||||||
|
// Unblock draw task once source layer is ready
|
||||||
|
otherLayer.sync(task.unblock);
|
||||||
|
|
||||||
|
// Block other layer until draw completes
|
||||||
|
// Note that the draw MAY have already been performed at this point,
|
||||||
|
// in which case creating a lock on the other layer will lead to
|
||||||
|
// deadlock (the draw task has already run and will thus never
|
||||||
|
// clear the lock)
|
||||||
|
if (!drawComplete)
|
||||||
|
layerLock = otherLayer.sync(null, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to true if this Layer should resize itself to accomodate the
|
* Set to true if this Layer should resize itself to accomodate the
|
||||||
* dimensions of any drawing operation, and false (the default) otherwise.
|
* dimensions of any drawing operation, and false (the default) otherwise.
|
||||||
@@ -424,11 +486,8 @@ Guacamole.Layer = function(width, height) {
|
|||||||
* destination.
|
* destination.
|
||||||
*/
|
*/
|
||||||
this.transfer = function(srcLayer, srcx, srcy, srcw, srch, x, y, transferFunction) {
|
this.transfer = function(srcLayer, srcx, srcy, srcw, srch, x, y, transferFunction) {
|
||||||
|
scheduleTaskSynced(srcLayer, function() {
|
||||||
|
|
||||||
var drawComplete = false;
|
|
||||||
var srcLock = null;
|
|
||||||
|
|
||||||
function doTransfer() {
|
|
||||||
if (layer.autosize != 0) fitRect(x, y, srcw, srch);
|
if (layer.autosize != 0) fitRect(x, y, srcw, srch);
|
||||||
|
|
||||||
var srcCanvas = srcLayer.getCanvas();
|
var srcCanvas = srcLayer.getCanvas();
|
||||||
@@ -473,38 +532,7 @@ Guacamole.Layer = function(width, height) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unblock the source layer now that draw is complete
|
});
|
||||||
if (srcLock != null)
|
|
||||||
srcLock.unblock();
|
|
||||||
|
|
||||||
// Flag operation as done
|
|
||||||
drawComplete = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we ARE the source layer, no need to sync.
|
|
||||||
// Syncing would result in deadlock.
|
|
||||||
if (layer === srcLayer)
|
|
||||||
scheduleTask(doTransfer);
|
|
||||||
|
|
||||||
// Otherwise synchronize copy operation with source layer
|
|
||||||
else {
|
|
||||||
|
|
||||||
// Currently blocked draw task
|
|
||||||
var task = scheduleTask(doTransfer, true);
|
|
||||||
|
|
||||||
// Unblock draw task once source layer is ready
|
|
||||||
srcLayer.sync(task.unblock);
|
|
||||||
|
|
||||||
// Block source layer until draw completes
|
|
||||||
// Note that the draw MAY have already been performed at this point,
|
|
||||||
// in which case creating a lock on the source layer will lead to
|
|
||||||
// deadlock (the draw task has already run and will thus never
|
|
||||||
// clear the lock)
|
|
||||||
if (!drawComplete)
|
|
||||||
srcLock = srcLayer.sync(null, true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -529,49 +557,14 @@ Guacamole.Layer = function(width, height) {
|
|||||||
* @param {Number} y The destination Y coordinate.
|
* @param {Number} y The destination Y coordinate.
|
||||||
*/
|
*/
|
||||||
this.copy = function(srcLayer, srcx, srcy, srcw, srch, x, y) {
|
this.copy = function(srcLayer, srcx, srcy, srcw, srch, x, y) {
|
||||||
|
scheduleTaskSynced(srcLayer, function() {
|
||||||
var drawComplete = false;
|
|
||||||
var srcLock = null;
|
|
||||||
|
|
||||||
function doCopy() {
|
|
||||||
if (layer.autosize != 0) fitRect(x, y, srcw, srch);
|
if (layer.autosize != 0) fitRect(x, y, srcw, srch);
|
||||||
|
|
||||||
var srcCanvas = srcLayer.getCanvas();
|
var srcCanvas = srcLayer.getCanvas();
|
||||||
if (srcCanvas.width != 0 && srcCanvas.height != 0)
|
if (srcCanvas.width != 0 && srcCanvas.height != 0)
|
||||||
displayContext.drawImage(srcCanvas, srcx, srcy, srcw, srch, x, y, srcw, srch);
|
displayContext.drawImage(srcCanvas, srcx, srcy, srcw, srch, x, y, srcw, srch);
|
||||||
|
|
||||||
// Unblock the source layer now that draw is complete
|
});
|
||||||
if (srcLock != null)
|
|
||||||
srcLock.unblock();
|
|
||||||
|
|
||||||
// Flag operation as done
|
|
||||||
drawComplete = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we ARE the source layer, no need to sync.
|
|
||||||
// Syncing would result in deadlock.
|
|
||||||
if (layer === srcLayer)
|
|
||||||
scheduleTask(doCopy);
|
|
||||||
|
|
||||||
// Otherwise synchronize copy operation with source layer
|
|
||||||
else {
|
|
||||||
|
|
||||||
// Currently blocked draw task
|
|
||||||
var task = scheduleTask(doCopy, true);
|
|
||||||
|
|
||||||
// Unblock draw task once source layer is ready
|
|
||||||
srcLayer.sync(task.unblock);
|
|
||||||
|
|
||||||
// Block source layer until draw completes
|
|
||||||
// Note that the draw MAY have already been performed at this point,
|
|
||||||
// in which case creating a lock on the source layer will lead to
|
|
||||||
// deadlock (the draw task has already run and will thus never
|
|
||||||
// clear the lock)
|
|
||||||
if (!drawComplete)
|
|
||||||
srcLock = srcLayer.sync(null, true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -648,15 +641,23 @@ Guacamole.Layer = function(width, height) {
|
|||||||
* for other operations (such as clip()) but a new path will be started
|
* for other operations (such as clip()) but a new path will be started
|
||||||
* once a path drawing operation (path() or rect()) is used.
|
* once a path drawing operation (path() or rect()) is used.
|
||||||
*
|
*
|
||||||
|
* @param {String} cap The line cap style. Can be "round", "square",
|
||||||
|
* or "butt".
|
||||||
|
* @param {String} join The line join style. Can be "round", "bevel",
|
||||||
|
* or "miter".
|
||||||
|
* @param {Number} thickness The line thickness in pixels.
|
||||||
* @param {Number} r The red component of the color to fill.
|
* @param {Number} r The red component of the color to fill.
|
||||||
* @param {Number} g The green component of the color to fill.
|
* @param {Number} g The green component of the color to fill.
|
||||||
* @param {Number} b The blue component of the color to fill.
|
* @param {Number} b The blue component of the color to fill.
|
||||||
* @param {Number} a The alpha component of the color to fill.
|
* @param {Number} a The alpha component of the color to fill.
|
||||||
*/
|
*/
|
||||||
this.strokeColor = function(r, g, b, a) {
|
this.strokeColor = function(cap, join, thickness, r, g, b, a) {
|
||||||
scheduleTask(function() {
|
scheduleTask(function() {
|
||||||
|
|
||||||
// Stroke with color
|
// Stroke with color
|
||||||
|
displayContext.lineCap = cap;
|
||||||
|
displayContext.lineJoin = join;
|
||||||
|
displayContext.lineWidth = thickness;
|
||||||
displayContext.strokeStyle = "rgba(" + r + "," + g + "," + b + "," + a/255.0 + ")";
|
displayContext.strokeStyle = "rgba(" + r + "," + g + "," + b + "," + a/255.0 + ")";
|
||||||
displayContext.stroke();
|
displayContext.stroke();
|
||||||
|
|
||||||
@@ -666,7 +667,6 @@ Guacamole.Layer = function(width, height) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills the current path with the specified color. The current path
|
* Fills the current path with the specified color. The current path
|
||||||
* is implicitly closed. The current path can continue to be reused
|
* is implicitly closed. The current path can continue to be reused
|
||||||
@@ -691,6 +691,66 @@ Guacamole.Layer = function(width, height) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stroke the current path with the image within the specified layer. The
|
||||||
|
* image data will be tiled infinitely within the stroke. The current path
|
||||||
|
* is implicitly closed. The current path can continue to be reused
|
||||||
|
* for other operations (such as clip()) but a new path will be started
|
||||||
|
* once a path drawing operation (path() or rect()) is used.
|
||||||
|
*
|
||||||
|
* @param {String} cap The line cap style. Can be "round", "square",
|
||||||
|
* or "butt".
|
||||||
|
* @param {String} join The line join style. Can be "round", "bevel",
|
||||||
|
* or "miter".
|
||||||
|
* @param {Number} thickness The line thickness in pixels.
|
||||||
|
* @param {Guacamole.Layer} srcLayer The layer to use as a repeating pattern
|
||||||
|
* within the stroke.
|
||||||
|
*/
|
||||||
|
this.strokeLayer = function(cap, join, thickness, srcLayer) {
|
||||||
|
scheduleTaskSynced(srcLayer, function() {
|
||||||
|
|
||||||
|
// Stroke with image data
|
||||||
|
displayContext.lineCap = cap;
|
||||||
|
displayContext.lineJoin = join;
|
||||||
|
displayContext.lineWidth = thickness;
|
||||||
|
displayContext.strokeStyle = displayContext.createPattern(
|
||||||
|
srcLayer.getCanvas(),
|
||||||
|
"repeat"
|
||||||
|
);
|
||||||
|
displayContext.stroke();
|
||||||
|
|
||||||
|
// Path now implicitly closed
|
||||||
|
pathClosed = true;
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills the current path with the image within the specified layer. The
|
||||||
|
* image data will be tiled infinitely within the stroke. The current path
|
||||||
|
* is implicitly closed. The current path can continue to be reused
|
||||||
|
* for other operations (such as clip()) but a new path will be started
|
||||||
|
* once a path drawing operation (path() or rect()) is used.
|
||||||
|
*
|
||||||
|
* @param {Guacamole.Layer} srcLayer The layer to use as a repeating pattern
|
||||||
|
* within the fill.
|
||||||
|
*/
|
||||||
|
this.fillLayer = function(srcLayer) {
|
||||||
|
scheduleTask(function() {
|
||||||
|
|
||||||
|
// Fill with image data
|
||||||
|
displayContext.fillStyle = displayContext.createPattern(
|
||||||
|
srcLayer.getCanvas(),
|
||||||
|
"repeat"
|
||||||
|
);
|
||||||
|
displayContext.fill();
|
||||||
|
|
||||||
|
// Path now implicitly closed
|
||||||
|
pathClosed = true;
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push current layer state onto stack.
|
* Push current layer state onto stack.
|
||||||
*/
|
*/
|
||||||
@@ -746,6 +806,31 @@ Guacamole.Layer = function(width, height) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the given affine transform (defined with three values from the
|
||||||
|
* transform's matrix).
|
||||||
|
*
|
||||||
|
* @param {Number} a The first value in the affine transform's matrix.
|
||||||
|
* @param {Number} b The second value in the affine transform's matrix.
|
||||||
|
* @param {Number} c The third value in the affine transform's matrix.
|
||||||
|
* @param {Number} d The fourth value in the affine transform's matrix.
|
||||||
|
* @param {Number} e The fifth value in the affine transform's matrix.
|
||||||
|
* @param {Number} f The sixth value in the affine transform's matrix.
|
||||||
|
*/
|
||||||
|
this.transform = function(a, b, c, d, e, f) {
|
||||||
|
scheduleTask(function() {
|
||||||
|
|
||||||
|
// Clear transform
|
||||||
|
displayContext.transform(
|
||||||
|
a, b, c,
|
||||||
|
d, e, f
|
||||||
|
/*0, 0, 1*/
|
||||||
|
);
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the channel mask for future operations on this Layer.
|
* Sets the channel mask for future operations on this Layer.
|
||||||
*
|
*
|
||||||
@@ -764,6 +849,21 @@ Guacamole.Layer = function(width, height) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the miter limit for stroke operations using the miter join. This
|
||||||
|
* limit is the maximum ratio of the size of the miter join to the stroke
|
||||||
|
* width. If this ratio is exceeded, the miter will not be drawn for that
|
||||||
|
* joint of the path.
|
||||||
|
*
|
||||||
|
* @param {Number} limit The miter limit for stroke operations using the
|
||||||
|
* miter join.
|
||||||
|
*/
|
||||||
|
this.setMiterLimit = function(limit) {
|
||||||
|
scheduleTask(function() {
|
||||||
|
displayContext.miterLimit = limit;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Initialize canvas dimensions
|
// Initialize canvas dimensions
|
||||||
display.width = width;
|
display.width = width;
|
||||||
display.height = height;
|
display.height = height;
|
||||||
|
Reference in New Issue
Block a user