Serialization of Ink
The Ink Serialization module provides algorithms for encoding and decoding ink content and related meta data. These algorithms are optimized to work with the Universal Ink Model.
The algorithms support the following features:
- Fast encoding and decoding
- Compact file size
- Portability across operating systems and devices
- Binary representation that can be embedded in different container formats
To read more about the encoding scheme, click here.
Handling model
The following illustrates how to manage the data used within the Universal Ink Model. Within the ink model, several data repositories -- as well as the ink tree, the views, and knowledge graph -- need to be managed if the information is required for the use case.

Ink Model
The first step is to create an instance of the InkModel.
- Kotlin
- C#
- JavaScript
inkModel = InkModel()
public class Serializer
{
...
public void Init()
{
InkDocument = new InkModel();
InkDocument.InkTree.Root = new StrokeGroupNode(Identifier.FromNewGuid());
}
class DataModel {
constructor() {
this.inkModel = new InkModel();
this.repository = new DataRepository();
this.manipulationsContext = new SpatialContext();
}
...
Input Context Repository
The input context describes capturing the sensor data. This information needs to be added by the application, but -- depending on the use case of the application -- it may not be needed. Storage of the sensor data is also optional.
The following sections provide some examples of how the context can be defined.
Environment
The environment in which the sensor data has been produced (the operating system, etc.) can be defined as follows:
- Kotlin
- C#
import com.wacom.ink.format.input.*
...
// Initialize environment
environment = Environment()
environment.putProperty("os.name", "android")
environment.putProperty("os.version.name", Build.VERSION.CODENAME)
environment.putProperty("os.version.code", Build.VERSION.SDK_INT.toString())
environment.putProperty("os.version.incremental", Build.VERSION.INCREMENTAL)
environment.putProperty("os.version.release", Build.VERSION.RELEASE)
environment.putProperty("wacom.ink.sdk.name", activity.getString(R.string.sdk_name))
environment.putProperty("wacom.ink.sdk.version", activity.getString(R.string.sdk_version))
// Init environment
mEnvironment.Properties["os.name"] = m_eas.OperatingSystem;
mEnvironment.Properties["os.version.code"] = System.Environment.OSVersion.Version.ToString();
mEnvironment.Seal();
InkInputProvider
The ink input provider represents the generic input data source. It identifies how the data has been generated (using touch input, mouse, stylus, hardware controller, etc). For each platform and device, the application has to decide which input device is used within the application and serialize within the ink model.
- Kotlin
- C#
- JavaScript
import com.wacom.ink.format.input.*
...
val toolType = when (event.getToolType(0)) {
MotionEvent.TOOL_TYPE_STYLUS -> InkInputType.PEN
MotionEvent.TOOL_TYPE_FINGER -> InkInputType.TOUCH
MotionEvent.TOOL_TYPE_MOUSE -> InkInputType.MOUSE
else -> InkInputType.PEN
}
val provider = InkInputProvider(toolType)
TBD
TBD
Input Device
The input device which has been used to produce the sensor data. Depending on the platform, there may be several input devices available. Some tablets already have a stylus, or one is available as an accessory. The following properties can be collected as provided, for instance by the platform itself:
- Kotlin
- C#
- JavaScript
import com.wacom.ink.format.input.*
...
// Initialize InputDevice
inputDevice = InputDevice()
inputDevice.putProperty("dev.id", Build.ID)
inputDevice.putProperty("dev.manufacturer", Build.MANUFACTURER)
inputDevice.putProperty("dev.brand", Build.BRAND)
inputDevice.putProperty("dev.model", Build.MODEL)
inputDevice.putProperty("dev.board", Build.BOARD)
inputDevice.putProperty("dev.hardware", Build.HARDWARE)
inputDevice.putProperty("dev.codename", Build.DEVICE)
inputDevice.putProperty("dev.display", Build.DISPLAY)
...
{
InputDevice inputDevice = new InputDevice();
inputDevice.Properties["dev.name"] = System.Environment.MachineName;
inputDevice.Seal();
Identifier inputDeviceId = inputDevice.Id;
bool res = InkDocument.InputConfiguration.Devices.Any((device) => device.Id == inputDeviceId);
if (!res)
{
InkDocument.InputConfiguration.Devices.Add(inputDevice);
}
return inputDevice;
}
/**
* Creates default input device instance, based on system information
*
* @param {Properties} envProps User defined env properties, like app.id for example
* @return {InkInput.InputDevice} default instance
*/
static async createInstance(envProps) {
let device = new this(...Array.from(arguments).slice(1));
if (typeof sysInfo == "undefined")
device.props["dev.graphics.resolution"] = `${screen.width}x${screen.height}`;
else {
let system = await sysInfo.system();
let cpu = await sysInfo.cpu();
let graphics = await sysInfo.graphics();
let display = graphics.displays.filter(d => d.main)[0];
let adapter = graphics.controllers[0];
device.props["dev.id"] = system.uuid.toLowerCase();
device.props["dev.manufacturer"] = system.manufacturer;
device.props["dev.model"] = system.model;
device.props["dev.cpu"] = `${cpu.manufacturer} ${cpu.brand} ${cpu.speed} - ${cpu.cores} core(s)`;
device.props["dev.graphics.display"] = `${display.model} ${display.currentResX}x${display.currentResY} (${display.pixeldepth} bit)`;
device.props["dev.graphics.adapter"] = `${adapter.model} ${adapter.vram} GB`;
}
device.environment = await Environment.createInstance(envProps);
return device;
}
...
let device = await InputDevice.createInstance({"app.id": "will3-sdk-for-ink-web-demo", "app.version": "1.0.0"});