mirror of
https://github.com/devcode-it/openstamanager.git
synced 2025-03-29 09:30:06 +01:00
Aggiornamento chiave di licenza per Wacom v2
This commit is contained in:
parent
2720e99581
commit
52400fac42
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -1,3 +1,8 @@
|
||||
/**
|
||||
* Copyright (C) 2023 Wacom.
|
||||
* Use of this source code is governed by the MIT License that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
function integrityStatusDesc(status) {
|
||||
switch (status) {
|
||||
case Module.IntegrityStatus.OK: return "Integrity correct";
|
||||
|
0
assets/src/js/wacom/sigCaptDialog/libs/stu_capture/stu-sdk.min.js → assets/src/js/wacom/common/libs/stu-sdk.min.js
vendored
Executable file → Normal file
0
assets/src/js/wacom/sigCaptDialog/libs/stu_capture/stu-sdk.min.js → assets/src/js/wacom/common/libs/stu-sdk.min.js
vendored
Executable file → Normal file
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "STU-SDK",
|
||||
"productName": "STU-SDK",
|
||||
"version": "1.0.0",
|
||||
"description": "STU SDK for Javascript",
|
||||
"dependencies": {
|
||||
"blueimp-md5": "^2.19.0",
|
||||
"sjcl": "^1.0.8"
|
||||
},
|
||||
"author": "Juan Garrido",
|
||||
"license": "Wacom"
|
||||
}
|
@ -1,826 +0,0 @@
|
||||
//
|
||||
// stu_capture.js
|
||||
//
|
||||
// Displays a form with 3 buttons on the STU pad and on the browser allowing user to input a signature.
|
||||
// The final signature is then reproduced on a second window on the PC screen
|
||||
//
|
||||
// Copyright (c) 2021 Wacom GmbH. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
var signatureForm;
|
||||
|
||||
function captureFromSTU(sigObj, integrityType, hash, extraData) {
|
||||
if (!signatureForm) {
|
||||
signatureForm = new SignatureForm(sigObj, integrityType, hash, extraData);
|
||||
}
|
||||
signatureForm.connect();
|
||||
}
|
||||
|
||||
class Point {
|
||||
constructor(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
// In order to simulate buttons, we have our own Button class that stores the bounds and event handler.
|
||||
// Using an array of these makes it easy to add or remove buttons as desired.
|
||||
// delegate void ButtonClick();
|
||||
function Button() {
|
||||
this.Bounds; // in Screen coordinates
|
||||
this.Text;
|
||||
this.Click;
|
||||
}
|
||||
|
||||
function Rectangle(x, y, width, height) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.Contains = function (pt) {
|
||||
if (((pt.x >= this.x) && (pt.x <= (this.x + this.width))) &&
|
||||
((pt.y >= this.y) && (pt.y <= (this.y + this.height)))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SignatureForm {
|
||||
|
||||
constructor(sigObj, integrityType, hash, extraData) {
|
||||
this.sigObj = sigObj;
|
||||
this.integrityType = integrityType;
|
||||
this.hash = hash;
|
||||
this.extraData = extraData;
|
||||
|
||||
// The mIsDown flag is used like this:
|
||||
// 0 = up
|
||||
// +ve = down, pressed on button number
|
||||
// -1 = down, inking
|
||||
// -2 = down, ignoring
|
||||
this.mIsDown = 0;
|
||||
|
||||
this.mPenData = new Array(); // Array of data being stored. This can be subsequently used as desired.
|
||||
this.currentDevice = null;
|
||||
|
||||
this.onClick = false;
|
||||
}
|
||||
|
||||
// Connect to the first device
|
||||
async connect() {
|
||||
if (!this.currentDevice) {
|
||||
let devices = await com.WacomGSS.STU.UsbDevice.requestDevices();
|
||||
if (devices.length > 0) {
|
||||
this.currentDevice = devices[0];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.mTablet = new com.WacomGSS.STU.Tablet();
|
||||
this.mTablet.setEncryptionHandler(new MyEncryptionHandler());
|
||||
this.mTablet.setEncryptionHandler2(new MyEncryptionHandler2());
|
||||
|
||||
try {
|
||||
await this.mTablet.usbConnect(this.currentDevice);
|
||||
this.mCapability = await this.mTablet.getCapability();
|
||||
this.mInformation = await this.mTablet.getInformation();
|
||||
this.mInkThreshold = await this.mTablet.getInkThreshold();
|
||||
|
||||
try {
|
||||
await this.mTablet.setPenDataOptionMode(com.WacomGSS.STU.Protocol.PenDataOptionMode.TimeCountSequence);
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
this.mTablet.addTabletHandler(this);
|
||||
|
||||
//if (this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.OperationMode_$LI$())) {
|
||||
//this.mSignatureMode = true;
|
||||
//}
|
||||
this.mSignatureMode = false;
|
||||
|
||||
const pixelWidth = (96*this.mCapability.tabletMaxX*0.01)/25.4;
|
||||
const pixelHeight = (96*this.mCapability.tabletMaxY*0.01)/25.4;
|
||||
//this.createModalWindow(this.mCapability.screenWidth, this.mCapability.screenHeight);
|
||||
this.createModalWindow(pixelWidth, pixelHeight);
|
||||
|
||||
this.mScaleX = this.canvas.width / this.mCapability.tabletMaxX;
|
||||
this.mScaleY = this.canvas.height / this.mCapability.tabletMaxY;
|
||||
|
||||
this.mBtns = new Array(3);
|
||||
this.mBtns[0] = new Button();
|
||||
this.mBtns[1] = new Button();
|
||||
this.mBtns[2] = new Button();
|
||||
|
||||
if (this.mSignatureMode) {
|
||||
|
||||
// LCD is 800x480; Button positions and sizes are fixed
|
||||
this.mBtns[0].Bounds = new Rectangle( 0, 431, 265, 48);
|
||||
this.mBtns[1].Bounds = new Rectangle(266, 431, 265, 48);
|
||||
this.mBtns[2].Bounds = new Rectangle(532, 431, 265, 48);
|
||||
} else if (this.mInformation.modelName != "STU-300") {
|
||||
|
||||
// Place the buttons across the bottom of the screen.
|
||||
const w2 = this.canvas.width / 3;
|
||||
const w3 = this.canvas.width / 3;
|
||||
const w1 = this.canvas.width - w2 - w3;
|
||||
const y = this.canvas.height * 6 / 7;
|
||||
const h = this.canvas.height - y;
|
||||
|
||||
this.mBtns[0].Bounds = new Rectangle(0, y, w1, h);
|
||||
this.mBtns[1].Bounds = new Rectangle(w1, y, w2, h);
|
||||
this.mBtns[2].Bounds = new Rectangle(w1 + w2, y, w3, h);
|
||||
|
||||
} else {
|
||||
// The STU-300 is very shallow, so it is better to utilise
|
||||
// the buttons to the side of the display instead.
|
||||
|
||||
const x = this.mCapability.screenWidth * 3 / 4;
|
||||
const w = this.mCapability.screenWidth - x;
|
||||
|
||||
const h2 = this.mCapability.screenHeight / 3;
|
||||
const h3 = this.mCapability.screenHeight / 3;
|
||||
const h1 = this.mCapability.screenHeight - h2 - h3;
|
||||
|
||||
this.mBtns[0].Bounds = new Rectangle(x, 0, w, h1);
|
||||
this.mBtns[1].Bounds = new Rectangle(x, h1, w, h2);
|
||||
this.mBtns[2].Bounds = new Rectangle(x, h1 + h2, w, h3);
|
||||
}
|
||||
|
||||
this.mBtns[0].Text = "Clear";
|
||||
this.mBtns[0].Click = this.btnClearClick.bind(this);
|
||||
this.mBtns[1].Text = "Cancel";
|
||||
this.mBtns[1].Click = this.btnCancelClick.bind(this);
|
||||
this.mBtns[2].Text = "OK";
|
||||
this.mBtns[2].Click = this.btnOkClick.bind(this);
|
||||
|
||||
// This application uses the same bitmap for both the screen and client (window).
|
||||
this.ctx.lineWidth = 1;
|
||||
this.ctx.strokeStyle = 'black';
|
||||
this.ctx.font = "30px Arial";
|
||||
|
||||
this.ctx.fillStyle = "white";
|
||||
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
|
||||
let encodingFlag = com.WacomGSS.STU.Protocol.ProtocolHelper.simulateEncodingFlag(this.mTablet.getProductId(), this.mCapability.ecodingFlag);
|
||||
// Disable color if the bulk driver isn't installed (supportsWrite())
|
||||
if ((encodingFlag & com.WacomGSS.STU.Protocol.EncodingFlag.EncodingFlag_24bit) != 0) {
|
||||
this.mEncodingMode = this.mTablet.supportsWrite() ? com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_24bit_Bulk : com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_24bit;
|
||||
} else if ((encodingFlag & com.WacomGSS.STU.Protocol.EncodingFlag.EncodingFlag_16bit) != 0) {
|
||||
this.mEncodingMode = this.mTablet.supportsWrite() ? com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_16bit_Bulk : com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_16bit;
|
||||
} else {
|
||||
// assumes 1bit is available
|
||||
this.mEncodingMode = com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_1bit;
|
||||
}
|
||||
|
||||
if (this.mSignatureMode && !await this.initializeSigMode()) {
|
||||
alert("Exception initializing Signature Mode, reverting to normal operation");
|
||||
this.mSignatureMode = false;
|
||||
}
|
||||
|
||||
if (!this.mSignatureMode) {
|
||||
let btnsColors = ["white", "white", "white"];
|
||||
if((this.mEncodingMode & (com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_16bit_Bulk | com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_24bit_Bulk)) != 0)
|
||||
btnsColors = ["lightgrey", "lightgrey", "lightgrey"];
|
||||
|
||||
let newCanvas = this.createScreenImage(btnsColors, "black", null);
|
||||
|
||||
//store the background image in order to be reuse it when clear the screen
|
||||
this.mCanvasBackgroundImage = newCanvas.toDataURL("image/jpeg");
|
||||
this.mDeviceBackgroundImage = com.WacomGSS.STU.Protocol.ProtocolHelper.resizeAndFlatten(newCanvas, 0, 0, newCanvas.width, newCanvas.height,
|
||||
this.mCapability.screenWidth, this.mCapability.screenHeight, this.mEncodingMode,0, "white", false, 0);
|
||||
|
||||
// If you wish to further optimize image transfer, you can compress the image using
|
||||
// the Zlib algorithm.
|
||||
const useZlibCompression = false;
|
||||
|
||||
if (this.mEncodingMode == com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_1bit && useZlibCompression) {
|
||||
this.mDeviceBackgroundImage = compress_using_zlib(this.mDeviceBackgroundImage); // insert compression here!
|
||||
this.mEncodingMode = com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_1bit_ZLib;
|
||||
}
|
||||
|
||||
// Initialize the screen
|
||||
await this.clearScreen();
|
||||
}
|
||||
|
||||
if ((this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.EncryptionStatus)) ||
|
||||
(await com.WacomGSS.STU.Protocol.ProtocolHelper.supportsEncryption(this.mTablet.getProtocol()))) {
|
||||
|
||||
await this.mTablet.startCapture(0xc0ffee);
|
||||
this.mIsEncrypted = true;
|
||||
}
|
||||
|
||||
// Enable the pen data on the screen (if not already)
|
||||
await this.mTablet.setInkingMode(com.WacomGSS.STU.Protocol.InkingMode.On);
|
||||
|
||||
this.willCanvas = document.createElement("canvas");
|
||||
this.willCanvas.id = "willCanvas";
|
||||
this.willCanvas.style.position = "absolute";
|
||||
this.willCanvas.style.top = this.canvas.style.top;
|
||||
this.willCanvas.style.left = this.canvas.style.left;
|
||||
this.willCanvas.height = this.canvas.height;
|
||||
this.willCanvas.width = this.canvas.width;
|
||||
this.mFormDiv.appendChild(this.willCanvas);
|
||||
|
||||
if (this.willCanvas.addEventListener) {
|
||||
this.willCanvas.addEventListener("click", this.onCanvasClick.bind(this), false);
|
||||
}
|
||||
|
||||
await this.initInkController(this.willCanvas);
|
||||
|
||||
} catch (e) {
|
||||
alert(e);
|
||||
}
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
// Ensure that you correctly disconnect from the tablet, otherwise you are
|
||||
// likely to get errors when wanting to connect a second time.
|
||||
if (this.mTablet != null) {
|
||||
if (this.mIsEncrypted) {
|
||||
await this.mTablet.endCapture();
|
||||
this.mIsEncrypted = false;
|
||||
}
|
||||
|
||||
await this.mTablet.setInkingMode(com.WacomGSS.STU.Protocol.InkingMode.Off);
|
||||
await this.mTablet.setClearScreen();
|
||||
await this.mTablet.disconnect();
|
||||
}
|
||||
|
||||
this.closeModalWindow();
|
||||
}
|
||||
|
||||
showLoadingScreen(value) {
|
||||
if (value) {
|
||||
//this.canvas.style.display = "none";
|
||||
this.mLoadingImageDiv.style.display = "block";
|
||||
} else {
|
||||
//this.canvas.style.display = "block";
|
||||
this.mLoadingImageDiv.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
createModalWindow(width, height) {
|
||||
this.mModalBackground = document.createElement('div');
|
||||
this.mModalBackground.id = "modal-background";
|
||||
this.mModalBackground.className = "active";
|
||||
this.mModalBackground.style.width = window.innerWidth;
|
||||
this.mModalBackground.style.height = window.innerHeight;
|
||||
document.getElementsByTagName('body')[0].appendChild(this.mModalBackground);
|
||||
|
||||
let titleBarHeight = 25;
|
||||
let margin = 2;
|
||||
this.mSignatureWindow = document.createElement('div');
|
||||
this.mSignatureWindow.id = "signatureWindow";
|
||||
this.mSignatureWindow.style.position = "absolute";
|
||||
this.mSignatureWindow.style.backgroundColor = "#0097d4";
|
||||
this.mSignatureWindow.style.top = (window.innerHeight / 2) - (height / 2) + "px";
|
||||
this.mSignatureWindow.style.left = (window.innerWidth / 2) - (width / 2) + "px";
|
||||
this.mSignatureWindow.style.width = (width + margin + margin) + "px";
|
||||
this.mSignatureWindow.style.height = (height+titleBarHeight + margin + margin) + "px";
|
||||
document.getElementsByTagName('body')[0].appendChild(this.mSignatureWindow);
|
||||
|
||||
this.mTitleBar = document.createElement("div");
|
||||
this.mTitleBar.id = "titleBar";
|
||||
this.mTitleBar.style.width = "100%";
|
||||
this.mTitleBar.style.height = (titleBarHeight-5)+"px";
|
||||
this.mTitleBar.innerHTML = this.mInformation.modelName;
|
||||
this.mSignatureWindow.appendChild(this.mTitleBar);
|
||||
|
||||
this.mFormDiv = document.createElement('div');
|
||||
//this.mFormDiv.id = "signatureWindow";
|
||||
//this.mFormDiv.className = "active";
|
||||
this.mFormDiv.style.position = "absolute";
|
||||
this.mFormDiv.style.margin = "2px 2px 2px 2px";
|
||||
this.mFormDiv.style.top = titleBarHeight;//(window.innerHeight / 2) - (height / 2) + "px";
|
||||
//this.mFormDiv.style.left = "10px";//(window.innerWidth / 2) - (width / 2) + "px";
|
||||
this.mFormDiv.style.width = width + "px";
|
||||
this.mFormDiv.style.height = height + "px";
|
||||
this.mSignatureWindow.appendChild(this.mFormDiv);
|
||||
//document.getElementsByTagName('body')[0].appendChild(this.mFormDiv);
|
||||
|
||||
this.canvas = document.createElement("canvas");
|
||||
this.canvas.id = "myCanvas";
|
||||
this.canvas.style.position = "absolute";
|
||||
this.canvas.height = this.mFormDiv.offsetHeight;
|
||||
this.canvas.width = this.mFormDiv.offsetWidth;
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
this.mFormDiv.appendChild(this.canvas);
|
||||
//this.canvas.style.display = "none";
|
||||
|
||||
//if (this.canvas.addEventListener) {
|
||||
//this.canvas.addEventListener("click", this.onCanvasClick.bind(this), false);
|
||||
//}
|
||||
|
||||
this.mLoadingImageDiv = document.createElement('div');
|
||||
this.mLoadingImageDiv.style.position = "absolute";
|
||||
this.mLoadingImageDiv.style.backgroundColor="white";
|
||||
this.mLoadingImageDiv.style.width = "100%";
|
||||
this.mLoadingImageDiv.style.height = "100%";
|
||||
this.mLoadingImageDiv.innerHTML = '<div id="loadingDiv"><table><tr><td><img src="../common/stu_capture/loading.gif"></td><td>Loading the image, this could take a few seconds...</td></tr></div>';
|
||||
this.mFormDiv.appendChild(this.mLoadingImageDiv);
|
||||
|
||||
$("#signatureWindow").draggable({handle:"#titleBar"});
|
||||
}
|
||||
|
||||
// Initialize Signature Mode (STU-540 only)
|
||||
async initializeSigMode() {
|
||||
// Buttons on bitmaps sent to the tablet must be in the order Cancel / OK / Clear. The tablet will then
|
||||
// reorder button images displayed according to parameters passed to it in OperationMode_Signature
|
||||
// This application uses Clear / Cancel / OK
|
||||
const btnOrder = [2, 0, 1];
|
||||
const btnsUpColors = ["blue", "red", "green"];
|
||||
const btnsDownColors = ["darkblue", "darkred", "darkgreen"];
|
||||
|
||||
let canvas = this.createScreenImage(btnsUpColors, "black", btnOrder);
|
||||
let bitmapData = com.WacomGSS.STU.Protocol.ProtocolHelper.resizeAndFlatten(canvas, 0, 0, canvas.width, canvas.height,
|
||||
this.mCapability.screenWidth, this.mCapability.screenHeight, this.mEncodingMode,
|
||||
com.WacomGSS.STU.Protocol.ProtocolHelper.Scale.Strech, "white", false, 0);
|
||||
await this.checkSigModeImage(false, bitmapData);
|
||||
|
||||
canvas = this.createScreenImage(btnsDownColors, "white", btnOrder);
|
||||
bitmapData = com.WacomGSS.STU.Protocol.ProtocolHelper.resizeAndFlatten(canvas, 0, 0, canvas.width, canvas.height,
|
||||
this.mCapability.screenWidth, this.mCapability.screenHeight, this.mEncodingMode,
|
||||
com.WacomGSS.STU.Protocol.ProtocolHelper.Scale.Strech, "white", false, 0);
|
||||
await this.checkSigModeImage(true, bitmapData);
|
||||
|
||||
let sigMode = new com.WacomGSS.STU.Protocol.OperationMode_Signature(2, btnOrder, 0, 0);
|
||||
await this.mTablet.setOperationMode(new com.WacomGSS.STU.Protocol.OperationMode(sigMode));
|
||||
|
||||
canvas = this.createScreenImage(btnsUpColors, "black", null);
|
||||
this.mCanvasBackgroundImage = canvas.toDataURL("image/jpeg");
|
||||
|
||||
this.clearScreen();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
createScreenImage(btnColors, txtColor, btnOrder) {
|
||||
let canvas = document.createElement("canvas");
|
||||
canvas.width = this.canvas.width;
|
||||
canvas.height = this.canvas.height;
|
||||
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeStyle = 'black';
|
||||
ctx.font = "30px Arial";
|
||||
|
||||
ctx.fillStyle = "white";
|
||||
ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
|
||||
// Draw the buttons
|
||||
for (let i = 0; i < this.mBtns.length; ++i) {
|
||||
// Button objects are created in the order, left-to-right, Clear / Cancel / OK
|
||||
// If reordering for Signature Mode (btnOrder != null), use bounds of another button when drawing
|
||||
// for image to be sent to tablet.
|
||||
let btn = this.mBtns[i];
|
||||
let bounds = btnOrder != null ? this.mBtns[btnOrder[i]].Bounds : this.mBtns[i].Bounds;
|
||||
|
||||
if (this.mEncodingMode != com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_1bit) {
|
||||
ctx.fillStyle = btnColors[i];
|
||||
ctx.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
}
|
||||
|
||||
ctx.fillStyle = txtColor;
|
||||
ctx.rect(bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
|
||||
let xPos = bounds.x + ((bounds.width / 2) - (ctx.measureText(btn.Text).width / 2));
|
||||
|
||||
let metrics = ctx.measureText(btn.Text);
|
||||
let fontHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
|
||||
let actualHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
|
||||
|
||||
let yOffset = bounds.height - ((bounds.height / 2) - (actualHeight / 2));
|
||||
/*if (m_information.idProduct == enumProductId.STU_300)
|
||||
yOffset = 28;
|
||||
else if (m_information.idProduct == enumProductId.STU_430)
|
||||
yOffset = 26;
|
||||
else
|
||||
yOffset = 40;*/
|
||||
ctx.fillText(btn.Text, xPos, bounds.y + yOffset);
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
|
||||
/*if ((this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.EncryptionStatus)) ||
|
||||
(await com.WacomGSS.STU.Protocol.ProtocolHelper.supportsEncryption(this.mTablet.getProtocol()))) {
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillText("\uD83D\uDD12", 20, 50);
|
||||
}*/
|
||||
return canvas;
|
||||
}
|
||||
|
||||
// Check if a Signature Mode screen image is already stored on the tablet. Download it if not.
|
||||
async checkSigModeImage(pushed, imageData) {
|
||||
let sigScreenImageNum = 2;
|
||||
let romStartImageData = com.WacomGSS.STU.Protocol.RomStartImageData.initializeSignature(this.mEncodingMode, pushed, sigScreenImageNum, [true, true, true]);
|
||||
|
||||
await this.mTablet.setRomImageHash(com.WacomGSS.STU.Protocol.OperationModeType.Signature_$LI$(), pushed, sigScreenImageNum);
|
||||
let romImgHash = await this.mTablet.getRomImageHash();
|
||||
|
||||
let writeImage = true;
|
||||
if (romImgHash.getResult() == 0) {
|
||||
// There is already an image stored on the tablet corresponding to this image number and pushed state:
|
||||
// compare image hashes to determine if we need to overwrite it.
|
||||
if (arrayEquals(md5.array(imageData), romImgHash.getHash())) {
|
||||
// Image hashes match: no need to write image again
|
||||
writeImage = false;
|
||||
}
|
||||
}
|
||||
// else - no image on pad, writeImage = true;
|
||||
|
||||
if (writeImage) {
|
||||
// no image on pad
|
||||
await this.mTablet.writeRomImage(romStartImageData, imageData);
|
||||
}
|
||||
}
|
||||
|
||||
async clearScreen() {
|
||||
if (window.WILL) {
|
||||
window.WILL.clear();
|
||||
} else {
|
||||
// repaint the background image on the screen.
|
||||
const outer = this;
|
||||
const image = new Image();
|
||||
image.onload = function () {
|
||||
outer.ctx.drawImage(image, 0, 0);
|
||||
}
|
||||
image.src = this.mCanvasBackgroundImage;
|
||||
}
|
||||
|
||||
this.showLoadingScreen(true);
|
||||
if (!this.mSignatureMode) {
|
||||
// note: There is no need to clear the tablet screen prior to writing an image.
|
||||
await this.mTablet.writeImage(this.mEncodingMode, this.mDeviceBackgroundImage);
|
||||
}
|
||||
|
||||
this.mPenData = new Array();
|
||||
this.mIsDown = 0;
|
||||
|
||||
this.showLoadingScreen(false);
|
||||
}
|
||||
|
||||
closeModalWindow() {
|
||||
this.deleteInkCanvas();
|
||||
document.getElementsByTagName('body')[0].removeChild(this.mSignatureWindow);
|
||||
const modalBackground = document.getElementById("modal-background");
|
||||
if (modalBackground) {
|
||||
document.getElementsByTagName('body')[0].removeChild(modalBackground);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
tabletToScreen(penData) {
|
||||
// Screen means LCD screen of the tablet.
|
||||
return new Point(penData.x * this.mScaleX, penData.y * this.mScaleY);
|
||||
}
|
||||
|
||||
async onSignatureEvent(keyValue) {
|
||||
switch (keyValue) {
|
||||
case 0:
|
||||
await this.btnCancelClick()
|
||||
break;
|
||||
case 1:
|
||||
await this.btnOkClick();
|
||||
break;
|
||||
case 2:
|
||||
await this.btnClearClick();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
onCanvasClick(event) {
|
||||
// Enable the mouse to click on the simulated buttons that we have displayed.
|
||||
|
||||
// Note that this can add some tricky logic into processing pen data
|
||||
// if the pen was down at the time of this click, especially if the pen was logically
|
||||
// also 'pressing' a button! This demo however ignores any that.
|
||||
|
||||
const posX = event.pageX - $("#willCanvas").offset().left;
|
||||
const posY = event.pageY - $("#willCanvas").offset().top;
|
||||
|
||||
for (let i = 0; i < this.mBtns.length; i++) {
|
||||
if (this.mBtns[i].Bounds.Contains(new Point(posX, posY))) {
|
||||
this.mBtns[i].Click();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async btnOkClick() {
|
||||
if (this.mPenData.length > 0) {
|
||||
await this.getCaptureData();
|
||||
await this.btnCancelClick();
|
||||
this.renderSignature = true;
|
||||
}
|
||||
this.onClick = false;
|
||||
|
||||
}
|
||||
|
||||
async btnClearClick() {
|
||||
if (this.mPenData.length > 0) {
|
||||
await this.clearScreen();
|
||||
}
|
||||
this.onClick = false;
|
||||
}
|
||||
|
||||
async btnCancelClick() {
|
||||
await this.disconnect();
|
||||
this.onClick = false;
|
||||
}
|
||||
|
||||
// Generate the signature image
|
||||
async getCaptureData() {
|
||||
//Create Stroke Data
|
||||
var strokeVector = new Module.StrokeVector();
|
||||
var currentStroke = new Module.PointVector();
|
||||
|
||||
var currentStrokeID = 0;
|
||||
var isDown = true;
|
||||
var hasDown = false;
|
||||
|
||||
for (let index = 0; index < this.mPenData.length; index++) {
|
||||
if (this.mPenData[index].sw == 0 && !hasDown) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hasDown = true;
|
||||
|
||||
if (isDown && this.mPenData[index].sw == 0 || !isDown && this.mPenData[index].sw == 1) {
|
||||
isDown = (this.mPenData[index].sw == 1);
|
||||
//Move the current stroke data into the strokes array
|
||||
strokeVector.push_back({'points': currentStroke});
|
||||
currentStroke.delete();
|
||||
currentStroke = new Module.PointVector();
|
||||
currentStrokeID++;
|
||||
}
|
||||
|
||||
var point = {
|
||||
'x': this.mPenData[index].x,
|
||||
'y': this.mPenData[index].y,
|
||||
'p': this.mPenData[index].pressure,
|
||||
't': this.mPenData[index].timeCount,
|
||||
'tilt': 0,
|
||||
'twist': 0,
|
||||
'is_down': this.mPenData[index].sw,
|
||||
'stroke_id': currentStrokeID
|
||||
};
|
||||
|
||||
currentStroke.push_back(point);
|
||||
}
|
||||
|
||||
//Create capture area character
|
||||
var device = {
|
||||
'device_max_X': this.mCapability.tabletMaxX,
|
||||
'device_max_Y': this.mCapability.tabletMaxY,
|
||||
'device_max_P': this.mCapability.tabletMaxPressure,
|
||||
'device_pixels_per_m_x': 100000,
|
||||
'device_pixels_per_m_y': 100000,
|
||||
'device_origin_X': 0,
|
||||
'device_origin_Y': 1,
|
||||
'has_tilt': false,
|
||||
'has_twist': false
|
||||
}
|
||||
|
||||
var uid2;
|
||||
try {
|
||||
// getUid2 will throw if pad doesn't support Uid2
|
||||
uid2 = mTablet.getUid2();
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
|
||||
if (!uid2) {
|
||||
uid2 = 0;
|
||||
}
|
||||
|
||||
var digitizerInfo = "STU;'"+this.mInformation.modelName+"';"+this.mInformation.firmwareMajorVersion+"."+((parseInt(this.mInformation.firmwareMinorVersion) >> 4) & 0x0f)+"."+(parseInt(this.mInformation.firmwareMinorVersion) & 0x0f)+";"+uid2;
|
||||
var nicInfo = "";
|
||||
var timeResolution = 1000;
|
||||
var who = "Test user";
|
||||
var why = "test signature";
|
||||
var where = "";
|
||||
|
||||
await this.sigObj.generateSignature(who, why, where, this.integrityType, this.hash, strokeVector, device, digitizerInfo, nicInfo, timeResolution, new Date());
|
||||
|
||||
// put the extra data
|
||||
for (const [key, value] of this.extraData) {
|
||||
this.sigObj.setExtraData(key, value);
|
||||
}
|
||||
|
||||
//this.hash.delete();
|
||||
strokeVector.delete();
|
||||
currentStroke.delete();
|
||||
}
|
||||
|
||||
onPenDataOption(penData, time) {
|
||||
this.onPenData(penData, time);
|
||||
}
|
||||
|
||||
onPenDataTimeCountSequence(penData, time) {
|
||||
this.onPenData(penData, time);
|
||||
}
|
||||
|
||||
onPenDataTimeCountSequenceEncrypted(penData, time) {
|
||||
this.onPenDataTimeCountSequence(penData, time);
|
||||
}
|
||||
|
||||
onPenDataEncryptedOption(penData, time) { // Process incoming pen data
|
||||
this.onPenData(penData.penData1, time);
|
||||
this.onPenData(penData.penData2, time);
|
||||
}
|
||||
|
||||
onPenDataEncrypted(penData, time) { // Process incoming pen data
|
||||
this.onPenData(penData.penData1, time);
|
||||
this.onPenData(penData.penData2, time);
|
||||
}
|
||||
|
||||
onPenData(penData, time) { // Process incoming pen data
|
||||
|
||||
// console.log(JSON.stringify(penData));
|
||||
|
||||
|
||||
if (this.onClick) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!penData.timeCount) {
|
||||
penData.timeCount = Math.trunc(time)%1000000;
|
||||
}
|
||||
|
||||
// when the pen goes behind borders there is a bug that onalsy return 0
|
||||
let pt = this.tabletToScreen(penData);
|
||||
|
||||
let btn = 0; // will be +ve if the pen is over a button.
|
||||
for (var i = 0; i < this.mBtns.length; ++i) {
|
||||
if (this.mBtns[i].Bounds.Contains(pt)) {
|
||||
btn = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mIsDown == 0)
|
||||
{
|
||||
const isDown = (penData.pressure > this.mInkThreshold.onPressureMark);
|
||||
|
||||
if (isDown)
|
||||
{
|
||||
// transition to down
|
||||
if (btn > 0)
|
||||
{
|
||||
// We have put the pen down on a button.
|
||||
// Track the pen without inking on the client.
|
||||
|
||||
this.mIsDown = btn;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have put the pen down somewhere else.
|
||||
// Treat it as part of the signature.
|
||||
|
||||
this.mIsDown = -1;
|
||||
this.mPenData.push(penData);
|
||||
this.mPainting = true;
|
||||
|
||||
var downEvent = new PointerEvent("pointerdown", {
|
||||
pointerId: 1,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
pointerType: "pen",
|
||||
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
|
||||
isPrimary: true,
|
||||
clientX: pt.x,
|
||||
clientY: pt.y,
|
||||
time: penData.timeCount
|
||||
});
|
||||
|
||||
window.WILL.begin(InkBuilder.createPoint(downEvent));
|
||||
}
|
||||
} else {
|
||||
// hover point
|
||||
this.mPenData.push(penData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const isDown = !(penData.pressure <= this.mInkThreshold.offPressureMark);
|
||||
if (!isDown)
|
||||
{
|
||||
// transition to up
|
||||
if (btn > 0) {
|
||||
// The pen is over a button
|
||||
|
||||
if (btn == this.mIsDown) {
|
||||
// The pen was pressed down over the same button as is was lifted now.
|
||||
// Consider that as a clicki!
|
||||
this.onClick = true; //
|
||||
this.mBtns[btn-1].Click();
|
||||
}
|
||||
}
|
||||
this.mIsDown = 0;
|
||||
|
||||
if (this.mPainting) {
|
||||
this.mPainting = false;
|
||||
this.mPenData.push(penData);
|
||||
|
||||
if ((penData.x == 0) && (penData.y == 0) && (penData.pressure == 0)) {
|
||||
penData.x = this.lastPenData.x;
|
||||
penData.y = this.lastPenData.y;
|
||||
pt = this.tabletToScreen(penData);
|
||||
}
|
||||
|
||||
var upEvent = new PointerEvent("pointerup", {
|
||||
pointerId: 1,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
pointerType: "pen",
|
||||
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
|
||||
isPrimary: true,
|
||||
clientX: pt.x,
|
||||
clientY: pt.y,
|
||||
time: penData.timeCount
|
||||
});
|
||||
|
||||
window.WILL.end(InkBuilder.createPoint(upEvent));
|
||||
}
|
||||
} else {
|
||||
if (this.mPainting) {
|
||||
this.mPenData.push(penData);
|
||||
|
||||
var moveEvent = new PointerEvent("pointermove", {
|
||||
pointerId: 1,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
pointerType: "pen",
|
||||
width: 10,
|
||||
height: 10,
|
||||
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
|
||||
isPrimary: true,
|
||||
clientX: pt.x,
|
||||
clientY: pt.y,
|
||||
time: penData.timeCount
|
||||
});
|
||||
|
||||
window.WILL.move(InkBuilder.createPoint(moveEvent));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
this.lastPenData = penData;
|
||||
}
|
||||
|
||||
onEventDataSignature(eventData) {
|
||||
this.onSignatureEvent(eventData.getKeyValue());
|
||||
}
|
||||
|
||||
onEventDataSignatureEncrypted(eventData) {
|
||||
this.onSignatureEvent(eventData.getKeyValue());
|
||||
}
|
||||
|
||||
// Capture any report exception.
|
||||
onGetReportException(exception) {
|
||||
try {
|
||||
exception.getException();
|
||||
} catch (e) {
|
||||
alert(e);
|
||||
}
|
||||
}
|
||||
|
||||
async initInkController(canvas) {
|
||||
const inkColor = "#0000ff";
|
||||
let inkCanvas = await new InkCanvasRaster(canvas, canvas.width, canvas.height);
|
||||
await BrushPalette.configure(inkCanvas.canvas.ctx);
|
||||
|
||||
window.WILL = inkCanvas;
|
||||
WILL.setColor(Color.fromHex(inkColor));
|
||||
WILL.type = "raster";
|
||||
await WILL.setTool("pen");
|
||||
}
|
||||
|
||||
async deleteInkCanvas() {
|
||||
await BrushPalette.delete();
|
||||
await window.WILL.delete();
|
||||
window.WILL = null;
|
||||
|
||||
if (this.renderSignature) {
|
||||
this.renderSignature = false;
|
||||
renderSignature(true);
|
||||
}
|
||||
}
|
||||
|
||||
onDisconnect(device) {
|
||||
if (device == this.currentDevice) {
|
||||
if (document.getElementById("modal-background")) {
|
||||
this.closeModalWindow();
|
||||
}
|
||||
alert(device.productName+" has been disconnected, please connect it again.");
|
||||
this.currentDevice = null;
|
||||
signatureForm = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,289 +0,0 @@
|
||||
/**
|
||||
* Classes for encryption on STU devices
|
||||
**/
|
||||
|
||||
function toHex(value, padding) {
|
||||
var hex = value.toString(16);
|
||||
return "0000000000000000".substr(0,padding-hex.length)+hex;
|
||||
}
|
||||
|
||||
function toHex2(value) { return toHex(value,2); }
|
||||
function toHex4(value) { return toHex(value,4); }
|
||||
function toHex8(value) { return toHex(value,8); }
|
||||
|
||||
function arrayToHex(v) {
|
||||
var s="";
|
||||
for (var i = 0; i < v.length; ++i)
|
||||
s = s + toHex2(v[i]);
|
||||
return s;
|
||||
}
|
||||
|
||||
function hexToArray(s) {
|
||||
var a = new Array();
|
||||
for (var i = 0; i < s.length;i+=2)
|
||||
a.push(parseInt("0x"+ s.substr(i,2),16));
|
||||
return a;
|
||||
}
|
||||
|
||||
function padLeft(str, len, pad) {
|
||||
if (typeof(pad) == "undefined") pad = ' ';
|
||||
str = str.toString();
|
||||
if (len > str.length)
|
||||
str = Array(len+1-str.length).join(pad) + str;
|
||||
return str;
|
||||
}
|
||||
|
||||
function base64UrlDecode(str) {
|
||||
str = atob(str.replace(/-/g, '+').replace(/_/g, '/'));
|
||||
var buffer = new Array(str.length);
|
||||
for(var i = 0; i < str.length; ++i) {
|
||||
buffer[i] = str.charCodeAt(i);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function arrayEquals(a, b) {
|
||||
return Array.isArray(a) &&
|
||||
Array.isArray(b) &&
|
||||
a.length === b.length &&
|
||||
a.every((val, index) => val === b[index]);
|
||||
}
|
||||
|
||||
function generateHexString(length) {
|
||||
var ret = "";
|
||||
while (ret.length < length) {
|
||||
ret += Math.random().toString(16).substring(2);
|
||||
}
|
||||
return ret.substring(0,length);
|
||||
}
|
||||
|
||||
function powMod(a, b, prime) {
|
||||
if (b <= BigInt(0)) {
|
||||
return (BigInt(1));
|
||||
} else if (b === BigInt(1)) {
|
||||
return a % prime;
|
||||
} else if (b % BigInt(2) === BigInt(0)) {
|
||||
return powMod((a * a) % prime, b / BigInt(2) | BigInt(0), prime) % prime;
|
||||
} else {
|
||||
return (powMod((a * a) % prime, b / BigInt(2) | BigInt(0), prime) * a) % prime;
|
||||
}
|
||||
}
|
||||
|
||||
class MyEncryptionHandler {
|
||||
|
||||
constructor() {
|
||||
this.clearKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the encryption handler
|
||||
*/
|
||||
reset() {
|
||||
this.clearKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all encryption key values
|
||||
*/
|
||||
clearKeys() {
|
||||
this.bigint_p = null;
|
||||
this.bigint_g = null;
|
||||
this.sjcl_keyAES = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if Diffie-Hellman key exchange is required
|
||||
* @return true if key exchange is required
|
||||
*/
|
||||
requireDH() {
|
||||
return this.bigint_p == null || this.bigint_g == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes parameters for Diffie-Hellman key exchange
|
||||
* @param dhPrime Diffie-Hellman prime number
|
||||
* @param dhBase Diffie-Hellman base number
|
||||
*/
|
||||
setDH(dhPrime, dhBase) {
|
||||
var p = dhPrime;
|
||||
var g = dhBase;
|
||||
|
||||
this.bigint_p = BigInt("0x"+arrayToHex(p));
|
||||
this.bigint_g = BigInt("0x"+arrayToHex(g));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a public key
|
||||
* @return 128-bit key, as array of bytes
|
||||
*/
|
||||
generateHostPublicKey() {
|
||||
// secret key
|
||||
let randomValues = new Uint8Array(64);
|
||||
window.crypto.getRandomValues(randomValues);
|
||||
this.bigint_a = BigInt("0x"+arrayToHex(randomValues));
|
||||
|
||||
// public key
|
||||
var bigint_A = powMod(this.bigint_g, this.bigint_a, this.bigint_p);
|
||||
|
||||
var hex_A = padLeft(bigint_A.toString(16), 32, '0');
|
||||
var A = hexToArray(hex_A);
|
||||
return A;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a shared key, given the tablet's public key
|
||||
* @param devicePublicKey the tablet's public key
|
||||
*/
|
||||
computeSharedKey(devicePublicKey) {
|
||||
var B = devicePublicKey;
|
||||
|
||||
var bigint_B = BigInt("0x"+arrayToHex(B));
|
||||
|
||||
var bigint_shared = powMod(bigint_B, this.bigint_a, this.bigint_p);
|
||||
|
||||
var str_shared = padLeft(bigint_shared.toString(16), 32, '0');
|
||||
|
||||
this.sjcl_keyAES = new sjcl.cipher.aes( sjcl.codec.hex.toBits(str_shared) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a block of encrypted data
|
||||
* @param data an array of bytes to decrypt
|
||||
* @return decrypted data
|
||||
*/
|
||||
decrypt(data) {
|
||||
var arr_cipherText = data;
|
||||
var hex_cipherText = arrayToHex(arr_cipherText);
|
||||
var sjcl_cipherText = sjcl.codec.hex.toBits(hex_cipherText);
|
||||
|
||||
var sjcl_plainText = this.sjcl_keyAES.decrypt(sjcl_cipherText);
|
||||
|
||||
var hex_plainText = sjcl.codec.hex.fromBits(sjcl_plainText);
|
||||
var arr_plainText = hexToArray(hex_plainText);
|
||||
return arr_plainText;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MyEncryptionHandler2 {
|
||||
|
||||
constructor() {
|
||||
this.clearKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the encryption handler
|
||||
*/
|
||||
reset() {
|
||||
this.clearKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all encryption key values
|
||||
*/
|
||||
clearKeys() {
|
||||
this.privateKey = null;
|
||||
this.keyAES = null;
|
||||
this.exponent = null;
|
||||
this.modulus = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the symmetric key type
|
||||
* @return a Protocol.SymmetricKeyType value
|
||||
*/
|
||||
getSymmetricKeyType() {
|
||||
return com.WacomGSS.STU.Protocol.SymmetricKeyType.AES256;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the asymmetric padding type
|
||||
* @return a Protocol.AsymmetricPaddingType value
|
||||
*/
|
||||
getAsymmetricPaddingType() {
|
||||
return com.WacomGSS.STU.Protocol.AsymmetricPaddingType.OAEP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the asymmetric key type
|
||||
* @return a Protocol.AsymmetricKeyType value
|
||||
*/
|
||||
getAsymmetricKeyType() {
|
||||
return com.WacomGSS.STU.Protocol.AsymmetricKeyType.RSA2048;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public key exponent
|
||||
* @return RSA public key exponent as a byte array
|
||||
*/
|
||||
async getPublicExponent() {
|
||||
const keyPair = await window.crypto.subtle.generateKey({
|
||||
name: "RSA-OAEP",
|
||||
modulusLength: 2048,
|
||||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
||||
hash: {
|
||||
name: "SHA-1"
|
||||
},
|
||||
},
|
||||
true, //wheter the key is extractable or not
|
||||
["encrypt", "decrypt"]);
|
||||
|
||||
this.privateKey = keyPair.privateKey;
|
||||
const publicKey = await window.crypto.subtle.exportKey("jwk", keyPair.publicKey);
|
||||
|
||||
// base64url-decode modulus
|
||||
this.modulus = base64UrlDecode(publicKey.n);
|
||||
|
||||
// base64url-decode exponent
|
||||
this.exponent = base64UrlDecode(publicKey.e);
|
||||
|
||||
return this.exponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a public key
|
||||
* @return generated key as a byte array
|
||||
*/
|
||||
async generatePublicKey() {
|
||||
return this.modulus
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses private key and padding type to decrypt an encrypted AES (symmetric) key to use in
|
||||
* subsequent calls to #decrypt.
|
||||
* @param data Encrypted AES key
|
||||
*/
|
||||
async computeSessionKey(data) {
|
||||
const key = await window.crypto.subtle.decrypt({
|
||||
name: "RSA-OAEP"
|
||||
},
|
||||
this.privateKey,
|
||||
Uint8Array.from(data)
|
||||
);
|
||||
|
||||
// replace additional left zeros
|
||||
const decryptKey = BigInt("0x"+arrayToHex(new Uint8Array(key)));
|
||||
const hexKey = padLeft(decryptKey.toString(16), 64, '0');
|
||||
|
||||
// SubtleCrypto only supports AES-CBC with PKCS#7 padding.
|
||||
// so we need to use another library as STU devices uses no padding.
|
||||
this.keyAES = new sjcl.cipher.aes(sjcl.codec.hex.toBits(hexKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a block of encrypted data
|
||||
* @param data an array of bytes to decrypt
|
||||
* @return decrypted data
|
||||
*/
|
||||
decrypt(data) {
|
||||
var hex_cipherText = arrayToHex(data);
|
||||
var sjcl_cipherText = sjcl.codec.hex.toBits(hex_cipherText);
|
||||
|
||||
var sjcl_plainText = this.keyAES.decrypt(sjcl_cipherText);
|
||||
|
||||
var hex_plainText = sjcl.codec.hex.fromBits(sjcl_plainText);
|
||||
var arr_plainText = hexToArray(hex_plainText);
|
||||
|
||||
return arr_plainText;
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
# js-ext ChangeLog
|
||||
|
||||
## 1.0.2
|
||||
|
||||
_2021-10-01_
|
||||
|
||||
### Updates
|
||||
- TypedArray extened with createSharedIntsance - instance with SharedArrayBuffer, various updates across TypedArray related with shared memory
|
||||
|
||||
## 1.0.1
|
||||
|
||||
_2021-06-01_
|
||||
|
||||
### Updates
|
||||
- Function Set, Location extension implemented
|
||||
- Number MAX_$Type constatnts implemented
|
||||
|
||||
## 1.0.0
|
||||
|
||||
_2020-07-01_
|
||||
|
||||
- First release
|
@ -1,7 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -1,26 +0,0 @@
|
||||
# js-ext
|
||||
|
||||
## Description
|
||||
|
||||
The Javascript extension. Provides additional functionality to classes when they are available and when particular functionality is missing.
|
||||
|
||||
* Object
|
||||
* String
|
||||
* Number
|
||||
* Function
|
||||
* Array
|
||||
* ArrayBuffer
|
||||
* TypedArray
|
||||
* Set
|
||||
* Screen
|
||||
* Location
|
||||
* HTMLElement
|
||||
* HTMLImageElement
|
||||
* Image
|
||||
* Canvas (Adds support for OffscreenCanvas when is not available)
|
||||
* DOMPoint
|
||||
* DOMRect
|
||||
* DOMMatrix
|
||||
|
||||
Functionallity extensions through not existant classes:
|
||||
* DOMSize
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "js-ext",
|
||||
"productName": "JavaScript Extensions",
|
||||
"version": "1.0.2",
|
||||
"description": "Additional functionality provider",
|
||||
"main": "js-ext-min.cjs",
|
||||
"module": "js-ext-min.js",
|
||||
"unpkg": "js-ext-min.js",
|
||||
"repository": "https://github.com/js-ext.git",
|
||||
"author": "Tzvetelin Vassilev",
|
||||
"homepage": "https://github.com/js-ext",
|
||||
"bugs": {
|
||||
"url": "https://github.com/js-ext/issues"
|
||||
},
|
||||
"license": "ISC"
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
# digital-ink ChangeLog
|
||||
|
||||
## 1.5.0 (3.0.7)
|
||||
|
||||
_2022-07-01_
|
||||
|
||||
### Updates
|
||||
- _BrushApplier_ optimizations - simplify transform - mat4 to mat2d
|
||||
- _RIFFEncoder_ and _RIFFDecoder_ LIST chunk support added
|
||||
- _InkBuilderSettings_ extended - keepAllData, keepSplineParameters options added
|
||||
- _InkPathProducer_ build method optional settings added, additional pipeline data could be achieved from the worker
|
||||
- _InkModel_ clear method implemented
|
||||
_ _SplineInterpolator_ is capable to process and SplineFragments as input
|
||||
- _InkBuilderAsync_ open / close methods added, open workers is a prerequisite for proper usage
|
||||
|
||||
### Breaking Changes
|
||||
- Long dependency update - ECMA 6 compatible version integrated
|
||||
- Manipulation module refactoring based on C# implementation
|
||||
- SpatialContext createInstance method is removed, clone method is provided
|
||||
- InkModel createCopyInstance method is removed, clone method is provided
|
||||
- ArrayPath / SharedPath primitives replaced from Path implementation
|
||||
- View name validation - for non valid names error is throwing
|
||||
- Interval type deprecated, SplineFragment replace it
|
||||
- _Stroke_ subStroke method is removed, because Interval dependency, slice replace it, based on SplineFragment
|
||||
|
||||
## 1.4.2 (3.0.6)
|
||||
|
||||
_2021-11-01_
|
||||
|
||||
### Updates
|
||||
- _ConvexHullChainProducerAsync_ worker _ConvexHullProvider_ as external resource
|
||||
- _Selector_ selection algorythm improvments
|
||||
- _InkModel_ version support added, reffers UIM version
|
||||
- _SplineParameter_ implementation and integration
|
||||
|
||||
## 1.4.1 (3.0.5)
|
||||
|
||||
_2021-10-01_
|
||||
|
||||
### Updates
|
||||
- _View_ tree property is deprecated, use root instead
|
||||
- _Stroke_ Stroke.onPipeline abstract static could be implemented to provide custom settings for pipeline
|
||||
- _Stroke_ target property is deprected, Target enum is obsolete, onPipeline should be implemented when specific behaiour is needed.
|
||||
- Pipeline refactoring, prediction control increased, POLYGON_SIMPLIFIER stage is deprecated, lastPipelineStage defaults to POLYGON_MERGER
|
||||
- _InkBuilderSettings_ concatSegments option added, mergePrediction is deprecated
|
||||
- ArrayPath / SharedPath primitives implemented
|
||||
- Polygon primitive implemented - shape and holes paths, vertices property provides access to triangulated geometry
|
||||
- InkPath2D refactored - list of polygons, vertices property provides access to triangulated geometry of all underlying polygons, representing the shape
|
||||
- Pipeline output update for some of stages - Polygon / InkPath2D
|
||||
|
||||
### Bugfixes
|
||||
- _Scalar_ refactoring, DIP fixed (pixel representation), DP and DPI included
|
||||
- _SensorChannel_ default resolution fix
|
||||
- _OffscreenCanvasGL_ height property fix
|
||||
|
||||
## 1.4.0 (3.0.4)
|
||||
|
||||
_2021-09-01_
|
||||
|
||||
### Breaking Changes
|
||||
- _StrokeRendererGL_ streamUpdatedArea is replaced with blendStroke2D for better integration between GL and 2D contexts
|
||||
- _InkCodec_ decodeInkModel is async
|
||||
|
||||
### Updates
|
||||
- _InputListener_ resize reason listeners added - for orientation, window resolution, screen resolution, InkController resize method argument reason provided, ResizeReason enum provided
|
||||
- _InputListener_ suppressKeys properly introduced, it configures ctrlKey, altKey, shiftKey and metaKey and by default if any of them is pressed ink is suppressed
|
||||
- _InputListener_ provides prediction to _InkController_ move method when is browser supported
|
||||
- _OffscreenLayer2D_ draws with alpha
|
||||
- _InkBuilderSettings_ excludedPipelineStages, lastPipelineStage option added
|
||||
- Stroke renderMode defaults to SOURCE_OVER, required
|
||||
- StrokeRenderers can batch strokes list, blendStrokes implemented
|
||||
- Brush2D shape frame based on 1 diameter provides thiner strokes generation
|
||||
- Selector functionallity bug-fixes
|
||||
- SpatialContext createInstance method provided - could be based on another context (RTree clone)
|
||||
- Ink data format update to v.3.1.0
|
||||
- InkOperation protocol is created
|
||||
- PrecisionDetection compression serialisation functionality introduced, InkCodec precisionCalculator optional property controlls it
|
||||
- TripleStore refactoring, extends Array
|
||||
|
||||
## 1.3.0 (3.0.3)
|
||||
|
||||
_2021-01-15_
|
||||
|
||||
### Breaking Changes
|
||||
- _InkBuilder_ configure method should be called only once before starting new path building
|
||||
- InkBuilderSettings onBuildComplete property is deprecated, InkBuilder onComplete property should be used instead
|
||||
|
||||
### Updates
|
||||
- _InputListener_ - affects ink input when surface transform is available
|
||||
- _Stroke_ style support implemented
|
||||
- _Color_ - hex property provides color as hex
|
||||
- _Matrix_
|
||||
- properties setters impl
|
||||
- is2D property impl
|
||||
- matrix3d support added
|
||||
- fromPoints static method impl
|
||||
- distribution file name updated
|
||||
- PipelineStage enum available
|
||||
- InkBuilderSettings updated, pipeline options added:
|
||||
- lastPipelineStep - controls where pipeline to complete
|
||||
- excludedPipelineStages - excludes stages from pipeline
|
||||
|
||||
### Bugfixes
|
||||
- _InputDevice_ - fix senosor input validation when pointer is not available
|
||||
- loading BrushGL assets in Safari
|
||||
|
||||
## 1.2.0 (3.0.2)
|
||||
|
||||
_2020-09-01_
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- _InkController_ - interface is updated, registerTouches(changedTouches) method is replaced with registerInputProvider(pointerID, isPrimary), getInkBuilder(changedTouches) with getInkBuilder(pointerID), implementation update is required
|
||||
- _InkBuilderAbstract_ - property touchID is renamed to pointerID
|
||||
|
||||
### Updates
|
||||
|
||||
- _InputListener_ - based on PointerEvent only, fallback class is provided when PointerEvent is not available which implementation is based on MouseEvent and TouchEvent
|
||||
- _SensorPoint_ - PointerEvent based InputListener extends SensorPoint with coalesced and predicted points, when available
|
||||
- _Matrix_ - provides access to additional properties like scaleX, translateX, etc.
|
||||
- _InkPath2D_ - 2D ink path type implemented and integrated
|
||||
- Layer and StrokeRender implementations extended with setTransform method
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- _PathPoint_ - transform properly applied rotation when available
|
||||
|
||||
## 1.1.0 (3.0.1)
|
||||
|
||||
_2020-08-11_
|
||||
|
||||
### Updates
|
||||
|
||||
- _Spline_ - transfrom functionallity provided
|
||||
- _Stroke_ - transform functionality updated - transform underlying spline and path if available
|
||||
- _Intersector_ - intersect2 method renamed to intersectSegmentation, doc update
|
||||
- _InkContext_ - drawSprite is replaced from drawSpritesBatch (batching points sprites)
|
||||
- _InputDevice_ - decouple sensor point building from ink builder, InputDevice handles building, validation and provides sensor layout as string array
|
||||
- _InkCanvas2D_ - context attributes support (Layers inherits canvas attributes)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- _InkModel_ - provide proper strokes order after manipulations
|
||||
- _StrokeDrawContext_ - randomSeed fix (int number instead long)
|
||||
- _StrokeRendererGL_ - renderer configuration color update, overrides path color
|
||||
- _InkGLContext_ - blend mode MIN fixed, blendMode as property instead method
|
||||
- _Matrix_ - fromMatrix method do not recreates Matrix when data is Matrix instance
|
||||
- _PathPointContext_ - improved attributes values analyse, added suppot for tocuh devices with radius range (0, 1)
|
||||
- _CurvatureBasedInterpolator_ - rotation bug-fix, ts and tf aplyed
|
||||
|
||||
## 1.0.0 (3.0.0)
|
||||
|
||||
_2020-07-01_
|
||||
|
||||
- First release
|
@ -1,9 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Wacom Co LTD (https://www.wacom.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -1,140 +0,0 @@
|
||||
# WILL SDK for ink
|
||||
|
||||
**Wacom Ink Layer Language (WILL™)** is a cross-platform digital ink technology.
|
||||
It is based on the needs of the end-user and Wacom's experience with different domains.
|
||||
WILL allows you to include premium digital inking features in your applications.
|
||||
It uses a modularized pipeline allowing each module to be configured, replaced, or omitted as required by the specific application, providing you with superior flexibility.
|
||||
|
||||
The newly introduced **Universal Ink Model** is a data model describing ink related data structures and meta-data concept to describe the semantic content of ink.
|
||||
You can also use the file encoding of the Universal Ink Model to exchange ink content between applications and cross-platform.
|
||||
|
||||
The WILL 3 Framework includes:
|
||||
|
||||
* Software libraries for multiple platforms (Windows, Android, iOS, Web)
|
||||
* Code samples illustrating particular functionality
|
||||
* A web-based **Ink Designer** to configure and test the pipeline
|
||||
* Comprehensive documentation, including step-by-step guides
|
||||
|
||||
## Design Concepts
|
||||
The following is an introduction to the Design Concepts for our WILL technology.
|
||||
|
||||
## Interoperability
|
||||
WILL 3.0 technology and its **Universal Ink Model** is platform and device agnostic, thus the specification does not focus on specific hardware platforms.
|
||||
Ink Markup Language **[InkML]** and Ink Serialized Format **[ISF]** are the most well-known formats for storing digital ink besides Wacom Ink Layer Language **[WILL]**.
|
||||
The previous version of WILL did not support the storage of sensor data samples for digital ink (e.g., timestamps, (x,y)-coordinates, or pressure values).
|
||||
WILL 3.0 gives the ability to store ink sensor samples along with the visual representation of digital ink as well as semantic metadata.
|
||||
As a result it is now possible to make a loss-less conversion of the Universal Ink Data format to other existing formats.
|
||||
|
||||
|
||||
### Natural
|
||||
Digital ink has to look natural and similar to real ink.
|
||||
To ensure that the visual appearance of the digital ink can be shared across platforms, WILL 3.0 contains all relevant data to present ink in a consistent way across all platforms.
|
||||
By using WILL particle ink rasterization, natural brushes can be configured to create artwork, as illustrated in *Figure 1*.
|
||||
|
||||

|
||||
|
||||
*Figure 1: Artwork created with raster / particle ink.*
|
||||
|
||||
### Active
|
||||
Mobile apps, Cloud application, or Cloud services have become a part of modern IT infrastructures.
|
||||
Thus, modern data formats need to address issues including:
|
||||
|
||||
* Unique identifiable IDs for devices
|
||||
* Streaming capability for partial updates of ink data
|
||||
* Document size reduction
|
||||
* Support for commonly used Web Standards such as JSON
|
||||
|
||||

|
||||
|
||||
*Figure 2: Active Ink.*
|
||||
|
||||
### Meta Data and Semantics
|
||||
There are three types of metadata:
|
||||
|
||||
- Descriptive
|
||||
- Structural
|
||||
- Administrative
|
||||
|
||||
*Descriptive metadata* are typically used for discovery and identification, as information used to search and locate an object such as title, author, subject, keyword, and publisher.
|
||||
WILL offers metadata for the description of Document and Author in the ink document.
|
||||
|
||||
*Structural metadata* give a description of how the components of an object are organised.
|
||||
The metadata for ink can be used to describe the structure of ink documents.
|
||||
|
||||
Finally, *administrative metadata* give information to help manage the source.
|
||||
They refer to the technical information including file type or when and how the file was created.
|
||||
Two sub-types of administrative metadata are *rights management metadata* and *preservation metadata*.
|
||||
Rights management metadata explain intellectual property rights, while preservation metadata contain information that is needed to preserve and save a resource.
|
||||
|
||||
*Semantic metadata* is slowly becoming the differentiator in the vocabulary of many vendors.
|
||||
Semantics is the study of meaning.
|
||||
As it applies to technology and unstructured content, it represents the ability to extract meaning from words, phrases, sentences, and larger units of text that provide the context within content, and is manually applied or automatically generated as semantic metadata to describe the object.
|
||||
Semantic metadata is typically leveraged to improve search, but any application that uses metadata can achieve significant benefits through the generation or application of semantic metadata.
|
||||
Thus, WILL metadata is based on established metadata for document and author descriptions and defines its own semantic metadata for ink.
|
||||
|
||||
### Sensor Data and Biometrics
|
||||
Another important objective in the design of the Universal Ink Model is to support the capture of sensor data from ink devices.
|
||||
For example, sensor data is used in the context of handwriting analysis, as well as signature capture and verification.
|
||||
|
||||
Some ink devices provide additional information *(see Figure 3)* that in most use cases is considered less important and may not be supported by all makes or types of devices.
|
||||
This includes:
|
||||
|
||||
* **Pressure** - the force applied to the nib of the pen
|
||||
* **Inclination** - the angle between the pen barrel and vertical
|
||||
* **Orientation** - the plain-direction of the pen from the nib
|
||||
* **Rotation** - the rotation of the barrel during signing
|
||||
|
||||

|
||||
|
||||
*Figure 3: Overview ink sensor channels.*
|
||||
|
||||
The forensic character of the data is of paramount importance, and means that the data-collection philosophy differs in many respects from competing signature technologies.
|
||||
A key principle is that during the collection of the signature, the software stores the data exactly as it is supplied by the device.
|
||||
Each type of data (e.g. position, time, pressure, etc.) is collected with metric information which describes the units being used by the device, and this is stored with the raw point data to allow the conversion to true units when required.
|
||||
The advantage of this is that the accuracy of the information is determined by the device and cannot be compromised by the conversion process.
|
||||
In addition to the pen-data, contextual data is collected and stored with the signature.
|
||||
This includes:
|
||||
|
||||
* The name of the signatory
|
||||
* The date and time at which the signature was given
|
||||
* The reason for signing
|
||||
* The make and type of digitizer being used
|
||||
* The type and version of the digitizer driver being used
|
||||
* The type and version of the operating system of the client PC being used
|
||||
* The Network Interface Card address of the PC
|
||||
|
||||
The objective is to store sensor data and the characteristics of the ink device alongside the visual representation of the digital ink.
|
||||
|
||||
## Technology
|
||||
The WILL technology is designed to be a platform-independent inking engine, providing the most relevant capabilities:
|
||||
|
||||
- **Ink Geometry Pipeline and Rendering** - Converts sensor data from an input device into a geometry which is rendered by a platform-specific rendering engine
|
||||
- **Ink Serialization** - Exchanges the rendering results, the collected sensor data, and relevant metadata; the Universal Ink Format is used to serialize and de-serialize the information
|
||||
- **Ink Manipulation** - Manipulates the generated geometry; the ink manipulation operations will be able to scale, move, rotate, and erase ink strokes (including exact split)
|
||||
|
||||
|
||||
---
|
||||
|
||||
# Additional resources
|
||||
|
||||
## Sample Code
|
||||
For further samples check Wacom's Developer additional samples, see [https://github.com/Wacom-Developer](https://github.com/Wacom-Developer)
|
||||
|
||||
## Documentation
|
||||
For further details on using the SDK see [WILL SDK for ink documentation](http://developer-docs.wacom.com/sdk-for-ink/)
|
||||
|
||||
The API Reference is available directly in the downloaded SDK.
|
||||
|
||||
## Support
|
||||
If you experience issues with the technology components, please see related [FAQs](http://developer-docs.wacom.com/faqs)
|
||||
|
||||
For further support file a ticket in our **Developer Support Portal** described here: [Request Support](http://developer-docs.wacom.com/faqs/docs/q-support/support)
|
||||
|
||||
## Developer Community
|
||||
Join our developer community:
|
||||
|
||||
- [LinkedIn - Wacom for Developers](https://www.linkedin.com/company/wacom-for-developers/)
|
||||
- [Twitter - Wacom for Developers](https://twitter.com/Wacomdevelopers)
|
||||
|
||||
## License
|
||||
This sample code is licensed under the [MIT License](https://choosealicense.com/licenses/mit/)
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,64 +0,0 @@
|
||||
{
|
||||
"name": "digital-ink",
|
||||
"version": "1.5.0",
|
||||
"productName": "WILL SDK for ink",
|
||||
"productVersion": "3.0.5",
|
||||
"description": "WILL™ SDK for ink supports a variety of input technologies and generates the highest quality, most attractive digital ink outputs via these modules: Path generation and smoothing, Rasterizer, Manipulation and Serialization",
|
||||
"main": "digital-ink-min.cjs",
|
||||
"module": "./digital-ink-min.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"node": {
|
||||
"import": "./digital-ink-min.cjs.mjs",
|
||||
"require": "./digital-ink-min.cjs"
|
||||
},
|
||||
"browser": {
|
||||
"import": "./digital-ink-min.mjs"
|
||||
},
|
||||
"default": "./digital-ink-min.js"
|
||||
},
|
||||
"./web-integrator": {
|
||||
"node": {
|
||||
"import": "./web-integrator/web-integrator.mjs",
|
||||
"require": "./web-integrator/web-integrator.cjs"
|
||||
},
|
||||
"default": "./web-integrator/web-integrator.js"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"canvas": "^2.9.1",
|
||||
"clipper-lib": "^6.4.2",
|
||||
"gl": "^5.0.0",
|
||||
"gl-matrix": "^3.4.3",
|
||||
"js-ext": "../../wacom/js-ext",
|
||||
"js-md5": "^0.7.3",
|
||||
"jszip": "^3.9.1",
|
||||
"long": "^5.2.0",
|
||||
"poly2tri": "^1.5.0",
|
||||
"protobufjs": "^6.11.2",
|
||||
"rbush": "^3.0.1",
|
||||
"systeminformation": "^5.11.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"files": [
|
||||
"*.*",
|
||||
"web-integrator/**",
|
||||
"workers/**"
|
||||
],
|
||||
"keywords": [
|
||||
"wacom",
|
||||
"ink",
|
||||
"canvas",
|
||||
"rasterization",
|
||||
"universal-ink-model"
|
||||
],
|
||||
"repository": "https://github.com/orgs/Wacom-Developer",
|
||||
"author": "Wacom Co., Ltd",
|
||||
"homepage": "https://developer.wacom.com",
|
||||
"bugs": {
|
||||
"url": "https://developer.wacom.com/developer-dashboard/support"
|
||||
},
|
||||
"license": "Wacom INK SDK Evaluation Agreement"
|
||||
}
|
@ -1 +0,0 @@
|
||||
"use strict";class e{static DEPENDENCIES_SRC="/node_modules";get dependenciesESM(){return{quickselect:`${this.src}/quickselect/index.js`,rbush:`${this.src}/rbush/index.js`,long:`${this.src}/long/index.js`,"gl-matrix":`${this.src}/gl-matrix/esm/index.js`,"js-ext":`${this.src}/js-ext/js-ext-min.mjs`,"digital-ink":`${this.src}/digital-ink/digital-ink-min.mjs`}}get devDependenciesESM(){return Object.assign({},this.dependenciesESM,{"js-ext":`${this.src}/js-ext/js-ext.mjs`,"digital-ink":`${this.src}/digital-ink/digital-ink.mjs`})}get dependenciesUMD(){return{"clipper-lib":`${this.src}/clipper-lib/clipper.js`,poly2tri:`${this.src}/poly2tri/dist/poly2tri.min.js`,protobufjs:`${this.src}/protobufjs/dist/protobuf.min.js`,"js-md5":`${this.src}/js-md5/build/md5.min.js`,jszip:`${this.src}/jszip/dist/jszip.min.js`,rbush:`${this.src}/rbush/rbush.js`,long:`${this.src}/long/umd/index.js`,"gl-matrix":`${this.src}/gl-matrix/gl-matrix.js`,"js-ext":`${this.src}/js-ext/js-ext-min.js`,"digital-ink":`${this.src}/digital-ink/digital-ink-min.js`}}get devDependenciesUMD(){return Object.assign({},this.dependenciesUMD,{poly2tri:`${this.src}/poly2tri/dist/poly2tri.js`,protobufjs:`${this.src}/protobufjs/dist/protobuf.js`,"js-md5":`${this.src}/js-md5/src/md5.js`,jszip:`${this.src}/jszip/dist/jszip.js`,"js-ext":`${this.src}/js-ext/js-ext.js`,"digital-ink":`${this.src}/digital-ink/digital-ink.js`})}constructor(t=!0,i=""){this.cdn=t||"function"==typeof DedicatedWorkerGlobalScope,this.src=i+e.DEPENDENCIES_SRC}build(){return this.dependencies||(e.dev?this.cdn?this.dependencies=Object.assign({},this.devDependenciesUMD):this.dependencies=Object.assign({},this.devDependenciesUMD,this.devDependenciesESM):this.cdn?this.dependencies=Object.assign({},this.dependenciesUMD):this.dependencies=Object.assign({},this.dependenciesUMD,this.dependenciesESM)),this.dependencies}include(e={}){this.dependencies=Object.assign(this.build(),e)}integrate(){if(this.build(),this.cdn)if("function"==typeof DedicatedWorkerGlobalScope)Object.values(this.dependencies).forEach((e=>self.importScripts(e)));else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main or worker thread!");Object.values(this.dependencies).forEach((e=>document.write(`<script type="text/javascript" src="${e}"><\/script>`)))}else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main thread!");{let e={imports:this.dependencies},t=document.createElement("script");t.setAttribute("type","importmap"),t.textContent=JSON.stringify(e,0,4),document.currentScript?document.currentScript.after(t):document.head.appendChild(t)}}}static linkWorkers(...e){for(let t of e){let e=t.buildWorkerURL().split(location.host).last,i=document.createElement("link");i.setAttribute("rel","modulepreload"),i.setAttribute("href",e),document.head.appendChild(i)}}static integrate(t){new e(!0,t).integrate()}static integrateECMA6(t,i){let s=new e(!1,i);s.include(t),s.integrate()}static getCDNImports(t){return new e(!0,t).build()}}module.exports=e;
|
@ -1 +0,0 @@
|
||||
var DigitalInkWebIntegrator=function(){"use strict";function e(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function t(e,t){for(var i=0;i<t.length;i++){var n=t[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}var i,n,s,c=function(){function i(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";e(this,i),this.cdn=t||"function"==typeof DedicatedWorkerGlobalScope,this.src=n+i.DEPENDENCIES_SRC}var n,s,c;return n=i,s=[{key:"dependenciesESM",get:function(){return{quickselect:"".concat(this.src,"/quickselect/index.js"),rbush:"".concat(this.src,"/rbush/index.js"),long:"".concat(this.src,"/long/index.js"),"gl-matrix":"".concat(this.src,"/gl-matrix/esm/index.js"),"js-ext":"".concat(this.src,"/js-ext/js-ext-min.mjs"),"digital-ink":"".concat(this.src,"/digital-ink/digital-ink-min.mjs")}}},{key:"devDependenciesESM",get:function(){return Object.assign({},this.dependenciesESM,{"js-ext":"".concat(this.src,"/js-ext/js-ext.mjs"),"digital-ink":"".concat(this.src,"/digital-ink/digital-ink.mjs")})}},{key:"dependenciesUMD",get:function(){return{"clipper-lib":"".concat(this.src,"/clipper-lib/clipper.js"),poly2tri:"".concat(this.src,"/poly2tri/dist/poly2tri.min.js"),protobufjs:"".concat(this.src,"/protobufjs/dist/protobuf.min.js"),"js-md5":"".concat(this.src,"/js-md5/build/md5.min.js"),jszip:"".concat(this.src,"/jszip/dist/jszip.min.js"),rbush:"".concat(this.src,"/rbush/rbush.js"),long:"".concat(this.src,"/long/umd/index.js"),"gl-matrix":"".concat(this.src,"/gl-matrix/gl-matrix.js"),"js-ext":"".concat(this.src,"/js-ext/js-ext-min.js"),"digital-ink":"".concat(this.src,"/digital-ink/digital-ink-min.js")}}},{key:"devDependenciesUMD",get:function(){return Object.assign({},this.dependenciesUMD,{poly2tri:"".concat(this.src,"/poly2tri/dist/poly2tri.js"),protobufjs:"".concat(this.src,"/protobufjs/dist/protobuf.js"),"js-md5":"".concat(this.src,"/js-md5/src/md5.js"),jszip:"".concat(this.src,"/jszip/dist/jszip.js"),"js-ext":"".concat(this.src,"/js-ext/js-ext.js"),"digital-ink":"".concat(this.src,"/digital-ink/digital-ink.js")})}},{key:"build",value:function(){return this.dependencies||(i.dev?this.cdn?this.dependencies=Object.assign({},this.devDependenciesUMD):this.dependencies=Object.assign({},this.devDependenciesUMD,this.devDependenciesESM):this.cdn?this.dependencies=Object.assign({},this.dependenciesUMD):this.dependencies=Object.assign({},this.dependenciesUMD,this.dependenciesESM)),this.dependencies}},{key:"include",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.dependencies=Object.assign(this.build(),e)}},{key:"integrate",value:function(){if(this.build(),this.cdn)if("function"==typeof DedicatedWorkerGlobalScope)Object.values(this.dependencies).forEach((function(e){return self.importScripts(e)}));else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main or worker thread!");Object.values(this.dependencies).forEach((function(e){return document.write('<script type="text/javascript" src="'.concat(e,'"><\/script>'))}))}else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main thread!");var e={imports:this.dependencies},t=document.createElement("script");t.setAttribute("type","importmap"),t.textContent=JSON.stringify(e,0,4),document.currentScript?document.currentScript.after(t):document.head.appendChild(t)}}}],c=[{key:"linkWorkers",value:function(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];for(var n=0,s=t;n<s.length;n++){var c=s[n],r=c.buildWorkerURL().split(location.host).last,o=document.createElement("link");o.setAttribute("rel","modulepreload"),o.setAttribute("href",r),document.head.appendChild(o)}}},{key:"integrate",value:function(e){new i(!0,e).integrate()}},{key:"integrateECMA6",value:function(e,t){var n=new i(!1,t);n.include(e),n.integrate()}},{key:"getCDNImports",value:function(e){return new i(!0,e).build()}}],s&&t(n.prototype,s),c&&t(n,c),Object.defineProperty(n,"prototype",{writable:!1}),i}();return s="/node_modules",(n="DEPENDENCIES_SRC")in(i=c)?Object.defineProperty(i,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):i[n]=s,c}();
|
@ -1 +0,0 @@
|
||||
class e{static DEPENDENCIES_SRC="/node_modules";get dependenciesESM(){return{quickselect:`${this.src}/quickselect/index.js`,rbush:`${this.src}/rbush/index.js`,long:`${this.src}/long/index.js`,"gl-matrix":`${this.src}/gl-matrix/esm/index.js`,"js-ext":`${this.src}/js-ext/js-ext-min.mjs`,"digital-ink":`${this.src}/digital-ink/digital-ink-min.mjs`}}get devDependenciesESM(){return Object.assign({},this.dependenciesESM,{"js-ext":`${this.src}/js-ext/js-ext.mjs`,"digital-ink":`${this.src}/digital-ink/digital-ink.mjs`})}get dependenciesUMD(){return{"clipper-lib":`${this.src}/clipper-lib/clipper.js`,poly2tri:`${this.src}/poly2tri/dist/poly2tri.min.js`,protobufjs:`${this.src}/protobufjs/dist/protobuf.min.js`,"js-md5":`${this.src}/js-md5/build/md5.min.js`,jszip:`${this.src}/jszip/dist/jszip.min.js`,rbush:`${this.src}/rbush/rbush.js`,long:`${this.src}/long/umd/index.js`,"gl-matrix":`${this.src}/gl-matrix/gl-matrix.js`,"js-ext":`${this.src}/js-ext/js-ext-min.js`,"digital-ink":`${this.src}/digital-ink/digital-ink-min.js`}}get devDependenciesUMD(){return Object.assign({},this.dependenciesUMD,{poly2tri:`${this.src}/poly2tri/dist/poly2tri.js`,protobufjs:`${this.src}/protobufjs/dist/protobuf.js`,"js-md5":`${this.src}/js-md5/src/md5.js`,jszip:`${this.src}/jszip/dist/jszip.js`,"js-ext":`${this.src}/js-ext/js-ext.js`,"digital-ink":`${this.src}/digital-ink/digital-ink.js`})}constructor(t=!0,i=""){this.cdn=t||"function"==typeof DedicatedWorkerGlobalScope,this.src=i+e.DEPENDENCIES_SRC}build(){return this.dependencies||(e.dev?this.cdn?this.dependencies=Object.assign({},this.devDependenciesUMD):this.dependencies=Object.assign({},this.devDependenciesUMD,this.devDependenciesESM):this.cdn?this.dependencies=Object.assign({},this.dependenciesUMD):this.dependencies=Object.assign({},this.dependenciesUMD,this.dependenciesESM)),this.dependencies}include(e={}){this.dependencies=Object.assign(this.build(),e)}integrate(){if(this.build(),this.cdn)if("function"==typeof DedicatedWorkerGlobalScope)Object.values(this.dependencies).forEach((e=>self.importScripts(e)));else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main or worker thread!");Object.values(this.dependencies).forEach((e=>document.write(`<script type="text/javascript" src="${e}"><\/script>`)))}else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main thread!");{let e={imports:this.dependencies},t=document.createElement("script");t.setAttribute("type","importmap"),t.textContent=JSON.stringify(e,0,4),document.currentScript?document.currentScript.after(t):document.head.appendChild(t)}}}static linkWorkers(...e){for(let t of e){let e=t.buildWorkerURL().split(location.host).last,i=document.createElement("link");i.setAttribute("rel","modulepreload"),i.setAttribute("href",e),document.head.appendChild(i)}}static integrate(t){new e(!0,t).integrate()}static integrateECMA6(t,i){let s=new e(!1,i);s.include(t),s.integrate()}static getCDNImports(t){return new e(!0,t).build()}}export{e as default};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -17,10 +17,14 @@ class StuCaptDialog {
|
||||
this.config.sizeMode = "stu";
|
||||
}
|
||||
|
||||
|
||||
this.config.strokeColor = config.strokeColor ?? "#0202FE";
|
||||
this.config.strokeSize = config.strokeSize ?? 6;
|
||||
this.config.showWait = config.showWait ?? true;
|
||||
this.config.stuDevice = config.stuDevice;
|
||||
|
||||
} else {
|
||||
this.config = {showWait:true, sizeMode:"stu"};
|
||||
this.config = {showWait:true, sizeMode:"stu", strokeColor:"#0202FE", strokeSize:6 };
|
||||
}
|
||||
|
||||
this.mPenData = Array();
|
||||
@ -36,40 +40,14 @@ class StuCaptDialog {
|
||||
* @param {string} - Reason for signing.
|
||||
* @param {IntegrityType} - Hash method to maintain the signature integrity. None by default.
|
||||
* @param {Hash} - Hash of an attached document. None by default.
|
||||
* @param {string} - osInfo, string indicating the OS.
|
||||
* @param {string} - nicInfo.
|
||||
**/
|
||||
async open(sigObj, who, why, extraData, integrityType, documentHash) {
|
||||
this.sigObj = sigObj;
|
||||
|
||||
if (who) {
|
||||
this.who = who;
|
||||
} else {
|
||||
this.who = 'Customer';
|
||||
}
|
||||
|
||||
if (why) {
|
||||
this.why = why;
|
||||
} else {
|
||||
this.why = 'Confirmed';
|
||||
}
|
||||
|
||||
this.extraData = extraData;
|
||||
|
||||
if (integrityType) {
|
||||
this.integrityType = integrityType;
|
||||
} else {
|
||||
this.integrityType = Module.KeyType.None;
|
||||
}
|
||||
|
||||
if (documentHash) {
|
||||
this.documentHash = documentHash;
|
||||
} else {
|
||||
this.documentHash = new Module.Hash(Module.HashType.None);
|
||||
}
|
||||
|
||||
if (!this.currentDevice) {
|
||||
async open(sigObj, who, why, where, extraData, integrityType, documentHash, osInfo, nicInfo) {
|
||||
if (!this.config.stuDevice) {
|
||||
let devices = await com.WacomGSS.STU.UsbDevice.requestDevices();
|
||||
if (devices.length > 0) {
|
||||
this.currentDevice = devices[0];
|
||||
this.config.stuDevice = devices[0];
|
||||
} else {
|
||||
throw "No STU devices found";
|
||||
}
|
||||
@ -86,8 +64,12 @@ class StuCaptDialog {
|
||||
this.mTablet.setEncryptionHandler2(this.config.encryption.encryptionHandler2);
|
||||
}
|
||||
}
|
||||
|
||||
await this.mTablet.usbConnect(this.currentDevice);
|
||||
|
||||
try {
|
||||
await this.mTablet.usbConnect(this.config.stuDevice);
|
||||
} catch (e) {
|
||||
alert("STU Device not found");
|
||||
}
|
||||
this.mCapability = await this.mTablet.getCapability();
|
||||
this.mInformation = await this.mTablet.getInformation();
|
||||
this.mInkThreshold = await this.mTablet.getInkThreshold();
|
||||
@ -156,25 +138,23 @@ class StuCaptDialog {
|
||||
//this.config.borderColor = "#cccccc";
|
||||
this.config.source = {mouse:false, touch:false, pen:false, stu:true},
|
||||
this.sigCaptDialog = new SigCaptDialog(this.config);
|
||||
this.config.will = this.sigCaptDialog.config.will;
|
||||
this.sigCaptDialog.getCaptureData = this.getCaptureData.bind(this);
|
||||
this.sigCaptDialog.addEventListener("clear", this.onClearBtn.bind(this));
|
||||
this.sigCaptDialog.addEventListener("cancel", this.onCancelBtn.bind(this));
|
||||
this.sigCaptDialog.addEventListener("ok", this.onOkBtn.bind(this));
|
||||
|
||||
await this.sigCaptDialog.open(this.sigObj, this.who, this.why, this.extraData, this.integrityType, this.documentHash);
|
||||
await this.sigCaptDialog.open(sigObj, who, why, where, extraData, integrityType, documentHash, osInfo, "", nicInfo);
|
||||
|
||||
//store the background image in order to be reuse it when clear the screen
|
||||
//store the background image in order for it to be reused when the screen is cleared
|
||||
let canvas = await this.drawImageToCanvas(this.sigCaptDialog.createScreenImage(useColor));
|
||||
let ctx = canvas.getContext("2d");
|
||||
this.mDeviceBackgroundImage = com.WacomGSS.STU.Protocol.ProtocolHelper.resizeAndFlatten(canvas, 0, 0, canvasWidth, canvasHeight,
|
||||
this.mCapability.screenWidth, this.mCapability.screenHeight, this.mEncodingMode, com.WacomGSS.STU.Protocol.ProtocolHelper.Scale.Stretch, "white", false, false);
|
||||
// Initialize the screen
|
||||
await this.clearScreen();
|
||||
this.mCapability.screenWidth, this.mCapability.screenHeight, this.mEncodingMode, com.WacomGSS.STU.Protocol.ProtocolHelper.Scale.Stretch, "white", false, false);
|
||||
|
||||
if (this.config.encryption) {
|
||||
if ((this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.EncryptionStatus)) ||
|
||||
(await com.WacomGSS.STU.Protocol.ProtocolHelper.supportsEncryption(this.mTablet.getProtocol()))) {
|
||||
await this.mTablet.startCapture(this.config.encryption.sessionID);
|
||||
(await com.WacomGSS.STU.Protocol.ProtocolHelper.supportsEncryption(this.mTablet.getProtocol()))) {
|
||||
await this.mTablet.startCapture(this.config.encryption.sessionID);
|
||||
this.mIsEncrypted = true;
|
||||
}
|
||||
}
|
||||
@ -183,14 +163,22 @@ class StuCaptDialog {
|
||||
if (useColor) {
|
||||
let htc = await this.mTablet.getHandwritingThicknessColor();
|
||||
|
||||
let components = this.hexToRgb(this.config.will.color);
|
||||
let components = this.hexToRgb(this.config.strokeColor);
|
||||
htc.penColor = this.rgb3216(components.r, components.g, components.b);
|
||||
htc.penThickness = this.config.strokeSize;
|
||||
await this.mTablet.setHandwritingThicknessColor(htc);
|
||||
}
|
||||
|
||||
const reportCountLengths = this.mTablet.getReportCountLengths();
|
||||
if (reportCountLengths[com.WacomGSS.STU.Protocol.ReportId.RenderingMode_$LI$()] !== undefined) {
|
||||
await this.mTablet.setRenderingMode(com.WacomGSS.STU.Protocol.RenderingMode.WILL);
|
||||
}
|
||||
|
||||
// Enable the pen data on the screen (if not already)
|
||||
await this.mTablet.setInkingMode(com.WacomGSS.STU.Protocol.InkingMode.On);
|
||||
|
||||
// Initialize the screen
|
||||
await this.clearScreen();
|
||||
}
|
||||
|
||||
rgb3216(r, g, b) {
|
||||
@ -261,6 +249,7 @@ class StuCaptDialog {
|
||||
|
||||
async clearScreen() {
|
||||
this.sigCaptDialog.stopCapture();
|
||||
await this.mTablet.setClearScreen();
|
||||
|
||||
if ((this.config.showWait) &&
|
||||
(this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.StartImageDataArea_$LI$()))) {
|
||||
@ -321,7 +310,6 @@ class StuCaptDialog {
|
||||
}
|
||||
|
||||
async onOkBtn() {
|
||||
await this.getCaptureData();
|
||||
await this.disconnect();
|
||||
this.onOkListeners.forEach(listener => listener());
|
||||
}
|
||||
@ -363,24 +351,22 @@ class StuCaptDialog {
|
||||
// transition to down we save the button pressed
|
||||
this.mBtnIndex = btnIndex;
|
||||
if (this.mBtnIndex == -1) {
|
||||
// We have put the pen down outside a buttom.
|
||||
// We have put the pen down outside a button.
|
||||
// Treat it as part of the signature.
|
||||
this.mPenData.push(penData);
|
||||
|
||||
var downEvent = new PointerEvent("pointerdown", {
|
||||
pointerId: 1,
|
||||
pointerType: "pen",
|
||||
pointerType: "stu",
|
||||
isPrimary: true,
|
||||
clientX: pt.x,
|
||||
clientY: pt.y,
|
||||
pressure: penData.pressure/this.mCapability.tabletMaxPressure
|
||||
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
|
||||
buttons: 1
|
||||
});
|
||||
|
||||
const point = window.DigitalInk.InkBuilder.createPoint(downEvent);
|
||||
point.timestamp = penData.timeCount;
|
||||
this.sigCaptDialog.draw("begin", point);
|
||||
this.sigCaptDialog.stopTimeOut();
|
||||
this.startDown = Date.now();
|
||||
//downEvent.timeStamp = penData.timeCount;
|
||||
this.sigCaptDialog.onDown(downEvent);
|
||||
}
|
||||
} else {
|
||||
// hover point
|
||||
@ -397,35 +383,35 @@ class StuCaptDialog {
|
||||
} else {
|
||||
var upEvent = new PointerEvent("pointerup", {
|
||||
pointerId: 1,
|
||||
pointerType: "pen",
|
||||
isPrimary: true,
|
||||
clientX: pt.x,
|
||||
clientY: pt.y,
|
||||
pressure: penData.pressure/this.mCapability.tabletMaxPressure
|
||||
});
|
||||
|
||||
const point = window.DigitalInk.InkBuilder.createPoint(upEvent);
|
||||
point.timestamp = penData.timeCount;
|
||||
this.sigCaptDialog.draw("end", point);
|
||||
this.mPenData.push(penData);
|
||||
this.sigCaptDialog.startTimeOut();
|
||||
this.sigCaptDialog.addTimeOnSurface(Date.now() - this.startDown);
|
||||
}
|
||||
} else {
|
||||
// continue inking
|
||||
var moveEvent = new PointerEvent("pointermove", {
|
||||
pointerId: 1,
|
||||
pointerType: "pen",
|
||||
pointerType: "stu",
|
||||
isPrimary: true,
|
||||
clientX: pt.x,
|
||||
clientY: pt.y,
|
||||
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
|
||||
buttons: 1
|
||||
});
|
||||
|
||||
//upEvent.timeStamp = penData.timeCount;
|
||||
this.sigCaptDialog.onUp(upEvent);
|
||||
this.mPenData.push(penData);
|
||||
}
|
||||
} else {
|
||||
// continue inking
|
||||
if (this.mBtnIndex == -1) {
|
||||
var moveEvent = new PointerEvent("pointermove", {
|
||||
pointerId: 1,
|
||||
pointerType: "stu",
|
||||
isPrimary: true,
|
||||
clientX: pt.x,
|
||||
clientY: pt.y,
|
||||
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
|
||||
buttons: 1
|
||||
});
|
||||
|
||||
const point = window.DigitalInk.InkBuilder.createPoint(moveEvent);
|
||||
point.timestamp = penData.timeCount;
|
||||
this.sigCaptDialog.draw("move", point);
|
||||
this.mPenData.push(penData);
|
||||
//moveEvent.timeStamp = penData.timeCount;
|
||||
this.sigCaptDialog.onMove(moveEvent);
|
||||
this.mPenData.push(penData);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.mIsDown = isDown;
|
||||
@ -434,7 +420,7 @@ class StuCaptDialog {
|
||||
/**
|
||||
* Generate the signature from the raw data.
|
||||
**/
|
||||
async getCaptureData() {
|
||||
getCaptureData() {
|
||||
//Create Stroke Data
|
||||
let strokeVector = new Module.StrokeVector();
|
||||
let currentStroke = new Module.PointVector();
|
||||
@ -485,7 +471,8 @@ class StuCaptDialog {
|
||||
'device_pixels_per_m_x': 100000,
|
||||
'device_pixels_per_m_y': 100000,
|
||||
'device_origin_X': 0,
|
||||
'device_origin_Y': 1
|
||||
'device_origin_Y': 1,
|
||||
'device_unit_pixels': false
|
||||
}
|
||||
|
||||
var uid2;
|
||||
@ -500,24 +487,39 @@ class StuCaptDialog {
|
||||
uid2 = 0;
|
||||
}
|
||||
|
||||
var digitizerInfo = "STU;'"+this.mInformation.modelName+"';"+this.mInformation.firmwareMajorVersion+"."+((parseInt(this.mInformation.firmwareMinorVersion) >> 4) & 0x0f)+"."+(parseInt(this.mInformation.firmwareMinorVersion) & 0x0f)+";"+uid2;
|
||||
var nicInfo = "";
|
||||
var timeResolution = 1000;
|
||||
var who = this.who;
|
||||
var why = this.why;
|
||||
var where = "";
|
||||
const digitizerInfo = "STU;'"+this.mInformation.modelName+"';"+this.mInformation.firmwareMajorVersion+"."+((parseInt(this.mInformation.firmwareMinorVersion) >> 4) & 0x0f)+"."+(parseInt(this.mInformation.firmwareMinorVersion) & 0x0f)+";"+uid2;
|
||||
const timeResolution = 1000;
|
||||
|
||||
await this.sigObj.generateSignature(who, why, where, this.integrityType, this.documentHash, strokeVector, device, digitizerInfo, nicInfo, timeResolution);
|
||||
|
||||
// put the extra data
|
||||
if (this.extraData) {
|
||||
for (const data of this.extraData) {
|
||||
this.sigObj.setExtraData(data.name, data.value);
|
||||
}
|
||||
}
|
||||
|
||||
strokeVector.delete();
|
||||
currentStroke.delete();
|
||||
const myPromise = new Promise((resolve, reject) => {
|
||||
try {
|
||||
const promise = this.sigCaptDialog.sigObj.generateSignature(this.sigCaptDialog.signatory, this.sigCaptDialog.reason, this.sigCaptDialog.where, this.sigCaptDialog.integrityType, this.sigCaptDialog.documentHash, strokeVector, device, this.sigCaptDialog.osInfo, digitizerInfo, this.sigCaptDialog.nicInfo, timeResolution);
|
||||
promise.then((value) => {
|
||||
if (value) {
|
||||
// put the extra data
|
||||
if (this.extraData) {
|
||||
for (const data of this.extraData) {
|
||||
this.sigObj.setExtraData(data.name, data.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
strokeVector.delete();
|
||||
currentStroke.delete();
|
||||
resolve(value);
|
||||
});
|
||||
|
||||
promise.catch(error => {
|
||||
strokeVector.delete();
|
||||
currentStroke.delete();
|
||||
reject(error);
|
||||
});
|
||||
} catch (exception) {
|
||||
strokeVector.delete();
|
||||
currentStroke.delete();
|
||||
reject(exception);
|
||||
}
|
||||
});
|
||||
|
||||
return myPromise;
|
||||
}
|
||||
|
||||
drawImageToCanvas(src){
|
||||
|
@ -1,5 +1,13 @@
|
||||
/* touch-action: none; is required to make pen works fine with WILL */
|
||||
/*#signatureWindow {touch-action: none;}*/
|
||||
body {
|
||||
-webkit-user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
/*touch-action: none;*/
|
||||
}
|
||||
|
||||
#modal-background {
|
||||
position: absolute;
|
||||
@ -27,4 +35,4 @@
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
}
|
@ -270,11 +270,10 @@ function wacom(){
|
||||
'modules/digital-ink/digital-ink-min.js',
|
||||
'common/will/tools.js',
|
||||
'modules/sjcl/sjcl.js',
|
||||
'sigCaptDialog/libs/stu_capture/stu-sdk.min.js',
|
||||
'sigCaptDialog/libs/stu_capture/stu_capture_encryption.js',
|
||||
'common/libs/signature_sdk.js',
|
||||
'common/libs/signature_sdk_helper.js',
|
||||
'modules/node-forge/dist/forge.min.js',
|
||||
'common/libs/signature_sdk_helper.js',
|
||||
'common/libs/stu-sdk.min.js',
|
||||
'modules/node-forge/dist/forge.min.js',
|
||||
'sigCaptDialog/sigCaptDialog.js',
|
||||
'sigCaptDialog/stuCaptDialog.js'
|
||||
];
|
||||
|
@ -54,27 +54,30 @@ echo '
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
const licence = "'.setting('Licenza Wacom SDK').'";
|
||||
var mSigObj;
|
||||
var documentHash;
|
||||
var mHash;
|
||||
var backgroundImage;
|
||||
var sigCaptDialog
|
||||
var stuCapDialog;
|
||||
|
||||
// This var will store the public and private keys for encryption.
|
||||
// Please note that this is only a demostration, but on a production application
|
||||
// for security reasons the private key should not be stored in a global variable.
|
||||
var encryptionKeys;
|
||||
|
||||
Module.onRuntimeInitialized = _ => {
|
||||
documentHash = new Module.Hash(Module.HashType.None);
|
||||
mSigObj = new Module.SigObj();
|
||||
mSigObj.setLicence(licence);
|
||||
Module.onRuntimeInitialized = _ => {
|
||||
mSigObj = new Module.SigObj();
|
||||
mHash = new Module.Hash(Module.HashType.SHA512);
|
||||
|
||||
// Here we need to set the licence. The easiest way is directly using
|
||||
// const promise = mSigObj.setLicence(key, secret);
|
||||
// however here the problem it is that we expose the key and secret publically.
|
||||
// if we want to hide the licence we can get the licence from an external server.
|
||||
// there is a php demo file in /common/licence_proxy.php
|
||||
//const promise = mSigObj.setLicenceProxy("url from where to get the licence");
|
||||
const promise = mSigObj.setLicence("'.setting('Licenza Wacom SDK - Key').'", "'.setting('Licenza Wacom SDK - Secret').'");
|
||||
promise.then(value => {});
|
||||
promise.catch(error => {
|
||||
alert(error);
|
||||
});
|
||||
}
|
||||
|
||||
function capture() {
|
||||
|
||||
let captureDiv = document.getElementById("signature-pad");
|
||||
captureDiv.style.width = "500px";
|
||||
captureDiv.style.height = "300px";
|
||||
@ -86,7 +89,7 @@ echo '
|
||||
stuCapDialog.addEventListener("ok", function() {
|
||||
renderSignature();
|
||||
});
|
||||
stuCapDialog.open(mSigObj, '.prepare($intervento->anagrafica->ragione_sociale).', "'.tr('Firma').'", [], Module.KeyType.SHA512, documentHash);
|
||||
stuCapDialog.open(mSigObj, "'.str_replace('"', "'", $intervento->anagrafica->ragione_sociale).'", "'.tr('Firma').'", null, null, Module.KeyType.SHA512, mHash);
|
||||
}
|
||||
|
||||
function generateConfig() {
|
||||
@ -188,7 +191,7 @@ echo '
|
||||
config.timeOut.onTimeOut = timeOutCallback;
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
function timeOutCallback(timeOnSurface) {
|
||||
const minTimeOnSurface = parseInt(300);
|
||||
@ -237,17 +240,6 @@ echo '
|
||||
}
|
||||
|
||||
async function renderSignature() {
|
||||
const image = await renderSignatureImage();
|
||||
|
||||
$("#signature-pad").hide();
|
||||
$("#image-signature").show();
|
||||
$("#btn-group-firma").show();
|
||||
|
||||
document.getElementById("image-signature").src = image;
|
||||
document.getElementById("firma_base64").value = image;
|
||||
}
|
||||
|
||||
async function renderSignatureImage() {
|
||||
// calculate the size
|
||||
let renderWidth = 500;
|
||||
let renderHeight = 300;
|
||||
@ -281,20 +273,27 @@ echo '
|
||||
renderWidth = Math.floor(renderWidth);
|
||||
renderHeight = Math.floor(renderHeight);
|
||||
renderWidth += renderWidth % 4;
|
||||
}
|
||||
|
||||
const backgroundColor = "'.setting('Sfondo firma tavoletta Wacom').'";
|
||||
|
||||
}
|
||||
|
||||
if (isRelative) {
|
||||
renderWidth = -96; //dpi
|
||||
renderHeight = -96;
|
||||
}
|
||||
|
||||
let canvas;
|
||||
const inkColor = "#000F55";
|
||||
const comboTools = "pen";
|
||||
const inkTool = tools["pen"];
|
||||
const image = await mSigObj.renderBitmap(renderWidth, renderHeight, "image/png", inkTool, inkColor, backgroundColor, 0, 0, renderFlags);
|
||||
return image;
|
||||
const backgroundColor = "'.setting('Sfondo firma tavoletta Wacom').'";
|
||||
try {
|
||||
const image = await mSigObj.renderBitmap(renderWidth, renderHeight, "image/png", 4, inkColor, backgroundColor, 0, 0, 0x400000);
|
||||
document.getElementById("image-signature").src = image;
|
||||
document.getElementById("firma_base64").value = image;
|
||||
} catch (e) {
|
||||
alert(e);
|
||||
}
|
||||
|
||||
$("#signature-pad").hide();
|
||||
$("#image-signature").show();
|
||||
$("#btn-group-firma").show();
|
||||
}
|
||||
|
||||
function mmToPx(mm) {
|
||||
@ -331,6 +330,6 @@ echo '
|
||||
|
||||
setTimeout(function() {
|
||||
capture();
|
||||
},1000);
|
||||
}, 1000);
|
||||
|
||||
</script>';
|
||||
|
@ -1,5 +1,17 @@
|
||||
<?php
|
||||
|
||||
// File e cartelle deprecate
|
||||
$files = [
|
||||
'assets/src/js/wacom/sigCaptDialog/libs/',
|
||||
];
|
||||
|
||||
foreach ($files as $key => $value) {
|
||||
$files[$key] = realpath(base_dir().'/'.$value);
|
||||
}
|
||||
|
||||
delete($files);
|
||||
|
||||
|
||||
/* Fix per file sql di update aggiornato dopo rilascio 2.4.35 */
|
||||
$has_column = null;
|
||||
$col_righe = $database->fetchArray('SHOW COLUMNS FROM `zz_groups`');
|
||||
|
@ -558,3 +558,7 @@ ORDER BY
|
||||
ragione_sociale" WHERE `name` = 'Tecnici e tariffe';
|
||||
UPDATE `zz_views` INNER JOIN `zz_modules` ON `zz_views`.`id_module` = `zz_modules`.`id` SET `zz_views`.`query` = '`an_anagrafiche`.`idanagrafica`' WHERE `zz_modules`.`name` = 'Tecnici e tariffe' AND `zz_views`.`name` = 'id';
|
||||
|
||||
-- Divisione chiave di licenza Wacom in 2 stringhe come da SDK v2
|
||||
UPDATE `zz_settings` SET `valore` = '' WHERE `nome` = 'Licenza Wacom SDK';
|
||||
UPDATE `zz_settings` SET `nome` = 'Licenza Wacom SDK - Key' WHERE `nome` = 'Licenza Wacom SDK';
|
||||
INSERT INTO `zz_settings` (`nome`, `valore`, `tipo`, `editable`, `sezione`, `order`) VALUES ('Licenza Wacom SDK - Secret', '', 'string', '1', 'Tavoletta Wacom', '1');
|
Loading…
x
Reference in New Issue
Block a user