stuCaptDialog.js
stuCaptDialog.js
The first constructor should be adjusted like such:
- Version 1
- Version 2
...
if (this.config.sizeMode == undefined) {
this.config.sizeMode = "stu";
}
this.config.showWait = config.showWait ?? true;
} else {
this.config = {showWait:true, sizeMode:"stu"};
}
...
...
if (this.config.sizeMode == undefined) {
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", strokeColor:"#0202FE", strokeSize:6 };
}
...
Within the open
function, there are a number of sections that require adjustment:
Firstly, starting from line 33:
- Version 1
- Version 2
...
/**
* Connect to the first STU device found, and open the capture dialog.
* @param {string} - Name of the person who is going to sign.
* @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.
**/
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.config.stuDevice) {
let devices = await com.WacomGSS.STU.UsbDevice.requestDevices();
if (devices.length > 0) {
this.config.stuDevice = devices[0];
} else {
throw "No STU devices found";
}
}
...
...
/**
* Connect to the first STU device found, and open the capture dialog.
* @param {string} - Name of the person who is going to sign.
* @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, where, extraData, integrityType, documentHash, osInfo, nicInfo) {
if (!this.config.stuDevice) {
let devices = await com.WacomGSS.STU.UsbDevice.requestDevices();
if (devices.length > 0) {
this.config.stuDevice = devices[0];
} else {
throw "No STU devices found";
}
}
...
Line 90:
- Version 1
- Version 2
await this.mTablet.usbConnect(this.currentDevice);
try {
await this.mTablet.usbConnect(this.config.stuDevice);
} catch (e) {
alert("STU Device not found");
}
Line 153:
- Version 1
- Version 2
this.config.width = canvasWidth;
this.config.height = canvasHeight;
this.config.title = this.mInformation.modelName;
//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.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);
//store the background image in order to be reuse it when clear the screen
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();
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);
this.mIsEncrypted = true;
}
}
// put color ink
if (useColor) {
let htc = await this.mTablet.getHandwritingThicknessColor();
let components = this.hexToRgb(this.config.will.color);
htc.penColor = this.rgb3216(components.r, components.g, components.b);
await this.mTablet.setHandwritingThicknessColor(htc);
}
// Enable the pen data on the screen (if not already)
await this.mTablet.setInkingMode(com.WacomGSS.STU.Protocol.InkingMode.On);
}
this.config.width = canvasWidth;
this.config.height = canvasHeight;
this.config.title = this.mInformation.modelName;
//this.config.borderColor = "#cccccc";
this.config.source = {mouse:false, touch:false, pen:false, stu:true},
this.sigCaptDialog = new SigCaptDialog(this.config);
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(sigObj, who, why, where, extraData, integrityType, documentHash, osInfo, "", nicInfo);
//store the background image in order to be reuse it when clear the screen
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);
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);
this.mIsEncrypted = true;
}
}
// put color ink
if (useColor) {
let htc = await this.mTablet.getHandwritingThicknessColor();
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();
}
There's an additional line to be added on cleanScreen
:
- Version 1
- Version 2
async clearScreen() {
this.sigCaptDialog.stopCapture();
if ((this.config.showWait) &&
(this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.StartImageDataArea_$LI$()))) {
await this.drawWait();
}
await this.mTablet.writeImage(this.mEncodingMode, this.mDeviceBackgroundImage);
this.sigCaptDialog.startCapture();
}
async clearScreen() {
this.sigCaptDialog.stopCapture();
await this.mTablet.setClearScreen();
if ((this.config.showWait) &&
(this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.StartImageDataArea_$LI$()))) {
await this.drawWait();
}
await this.mTablet.writeImage(this.mEncodingMode, this.mDeviceBackgroundImage);
this.sigCaptDialog.startCapture();
}
On onOkBtn
, an await needs to be omitted.
- Version 1
- Version 2
async onOkBtn() {
await this.getCaptureData();
await this.disconnect();
this.onOkListeners.forEach(listener => listener());
}
async onOkBtn() {
await this.disconnect();
this.onOkListeners.forEach(listener => listener());
}
The function onPenData
requires the following updates:
- Version 1
- Version 2
...
var downEvent = new PointerEvent("pointerdown", {
pointerId: 1,
pointerType: "pen",
isPrimary: true,
clientX: pt.x,
clientY: pt.y,
pressure: penData.pressure/this.mCapability.tabletMaxPressure
});
const point = window.DigitalInk.InkBuilder.createPoint(downEvent);
point.timestamp = penData.timeCount;
this.sigCaptDialog.draw("begin", point);
this.sigCaptDialog.stopTimeOut();
this.startDown = Date.now();
}
} else {
// hover point
this.mPenData.push(penData);
}
} else {
if (!isDown) {
// transition to up
if (this.mBtnIndex > -1) {
if (btnIndex == this.mBtnIndex) {
// The pen is over the same button that was pressed
this.sigCaptDialog.clickButton(this.mBtnIndex);
}
} 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",
isPrimary: true,
clientX: pt.x,
clientY: pt.y,
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
});
const point = window.DigitalInk.InkBuilder.createPoint(moveEvent);
point.timestamp = penData.timeCount;
this.sigCaptDialog.draw("move", point);
this.mPenData.push(penData);
}
}
this.mIsDown = isDown;
}
...
var downEvent = new PointerEvent("pointerdown", {
pointerId: 1,
pointerType: "stu",
isPrimary: true,
clientX: pt.x,
clientY: pt.y,
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
buttons: 1
});
//downEvent.timeStamp = penData.timeCount;
this.sigCaptDialog.onDown(downEvent);
}
} else {
// hover point
this.mPenData.push(penData);
}
} else {
if (!isDown) {
// transition to up
if (this.mBtnIndex > -1) {
if (btnIndex == this.mBtnIndex) {
// The pen is over the same button that was pressed
this.sigCaptDialog.clickButton(this.mBtnIndex);
}
} else {
var upEvent = new PointerEvent("pointerup", {
pointerId: 1,
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
});
//moveEvent.timeStamp = penData.timeCount;
this.sigCaptDialog.onMove(moveEvent);
this.mPenData.push(penData);
}
}
}
this.mIsDown = isDown;
}
Finally, the function getCaptureData
requires these updates:
Firstly, the function no longer requires asynchrony.
- Version 1
- Version 2
async getCaptureData()
getCaptureData()
The remaining code requires these adjustments:
- Version 1
- Version 2
//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
}
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 = this.who;
var why = this.why;
var where = "";
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();
}
//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,
'device_unit_pixels': false
}
var uid2;
try {
// getUid2 will throw if pad doesn't support Uid2
uid2 = mTablet.getUid2();
}
catch (e) {
}
if (!uid2) {
uid2 = 0;
}
const digitizerInfo = "STU;'"+this.mInformation.modelName+"';"+this.mInformation.firmwareMajorVersion+"."+((parseInt(this.mInformation.firmwareMinorVersion) >> 4) & 0x0f)+"."+(parseInt(this.mInformation.firmwareMinorVersion) & 0x0f)+";"+uid2;
const timeResolution = 1000;
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;
}