Dear developers,
The following patch adds the possibility (with the default parameters it
have no effect) to remove distortion on the borders of the screen by
defining a border width, if the stylus is in the border (according to its
width) the position of the cursor is corrected by a polynomial of degree 3.
The four coefficients of the polynomial must also be given in parameter.
Therefore there is 4(topx topy bottomx bottomy) x (1(width)+4(polynomial
coefficients)) = 20 floating point values in the parameter.
To find the appropriate parameters I am creating a calibration tool, it
calibrate the center of the screen then it calibrate the borders.
git link : https://github.com/antigol/wacom-distortion
The calibration tool is still in development but it seems to work.
Yours faithfully,
Mario Geiger
diff --git include/wacom-properties.h include/wacom-properties.h
index b845083..54e7793 100644
--- include/wacom-properties.h
+++ include/wacom-properties.h
@@ -27,6 +27,9 @@
/* 32 bit, 4 values, top x, top y, bottom x, bottom y */
#define WACOM_PROP_TABLET_AREA "Wacom Tablet Area"
+/* 32 bit, 4x5=20 values, 4x[border width, polynomial coefficient x^3, x^2, x, 1] */
+#define WACOM_PROP_TABLET_DISTORTION "Wacom Border Distortion"
+
/* 8 bit, 1 value, [0 - 3] (NONE, CW, CCW, HALF) */
#define WACOM_PROP_ROTATION "Wacom Rotation"
diff --git src/wcmCommon.c src/wcmCommon.c
index 9408f42..f8be62e 100644
--- src/wcmCommon.c
+++ src/wcmCommon.c
@@ -438,6 +438,21 @@ static void sendCommonEvents(InputInfoPtr pInfo, const WacomDeviceState* ds,
sendWheelStripEvents(pInfo, ds, first_val, num_vals, valuators);
}
+static double wcmBorderDistortionCorrection(double coord, float border, float* polynomial)
+{
+ if (coord < border) {
+ double x = coord;
+ coord = polynomial[0];
+ coord *= x;
+ coord += polynomial[1]; // I wonder if double+float is slower than double+double
+ coord *= x;
+ coord += polynomial[2];
+ coord *= x;
+ coord += polynomial[3];
+ }
+ return coord;
+}
+
/* rotate x and y before post X inout events */
void wcmRotateAndScaleCoordinates(InputInfoPtr pInfo, int* x, int* y)
{
@@ -446,19 +461,36 @@ void wcmRotateAndScaleCoordinates(InputInfoPtr pInfo, int* x, int* y)
DeviceIntPtr dev = pInfo->dev;
AxisInfoPtr axis_x, axis_y;
int tmp_coord;
+ double f;
/* scale into on topX/topY area */
axis_x = &dev->valuator->axes[0];
axis_y = &dev->valuator->axes[1];
/* Don't try to scale relative axes */
- if (axis_x->max_value > axis_x->min_value)
- *x = xf86ScaleAxis(*x, axis_x->max_value, axis_x->min_value,
- priv->bottomX, priv->topX);
-
- if (axis_y->max_value > axis_y->min_value)
- *y = xf86ScaleAxis(*y, axis_y->max_value, axis_y->min_value,
- priv->bottomY, priv->topY);
+ if (axis_x->max_value > axis_x->min_value) {
+ f = (*x - priv->topX) / (double)(priv->bottomX - priv->topX);
+ f = wcmBorderDistortionCorrection(f, priv->distortion_topX_border, priv->distortion_topX_poly);
+ f = 1.0 - f;
+ f = wcmBorderDistortionCorrection(f, priv->distortion_bottomX_border, priv->distortion_bottomX_poly);
+ f = 1.0 - f;
+
+ *x = round(f * (axis_x->max_value - axis_x->min_value) + axis_x->min_value);
+ if (*x < axis_x->min_value) *x = axis_x->min_value;
+ if (*x > axis_x->max_value) *x = axis_x->max_value;
+ }
+
+ if (axis_y->max_value > axis_y->min_value) {
+ f = (*y - priv->topY) / (double)(priv->bottomY - priv->topY);
+ f = wcmBorderDistortionCorrection(f, priv->distortion_topY_border, priv->distortion_topY_poly);
+ f = 1.0 - f;
+ f = wcmBorderDistortionCorrection(f, priv->distortion_bottomY_border, priv->distortion_bottomY_poly);
+ f = 1.0 - f;
+
+ *y = round(f * (axis_y->max_value - axis_y->min_value) + axis_y->min_value);
+ if (*y < axis_y->min_value) *y = axis_y->min_value;
+ if (*y > axis_y->max_value) *y = axis_y->max_value;
+ }
/* coordinates are now in the axis rage we advertise for the device */
diff --git src/wcmXCommand.c src/wcmXCommand.c
index 346ff61..ec0d81c 100644
--- src/wcmXCommand.c
+++ src/wcmXCommand.c
@@ -33,6 +33,12 @@
#define XI_PROP_PRODUCT_ID "Device Product ID"
#endif
+#ifndef XATOM_FLOAT
+#define XATOM_FLOAT "FLOAT"
+#endif
+
+static Atom float_type;
+
static void wcmBindToSerial(InputInfoPtr pInfo, unsigned int serial);
/*****************************************************************************
@@ -82,6 +88,7 @@ int wcmDevSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode)
static Atom prop_devnode;
static Atom prop_rotation;
static Atom prop_tablet_area;
+static Atom prop_distortion;
static Atom prop_pressurecurve;
static Atom prop_serials;
static Atom prop_serial_binding;
@@ -204,11 +211,23 @@ static Atom InitWcmAtom(DeviceIntPtr dev, const char *name, Atom type, int forma
return atom;
}
+static Atom InitFloatAtom(DeviceIntPtr dev, const char *name, int nvalues, float *values)
+{
+ Atom atom;
+
+ atom = MakeAtom(name, strlen(name), TRUE);
+ XIChangeDeviceProperty(dev, atom, float_type, 32,
+ PropModeReplace, nvalues, values, FALSE);
+ XISetDevicePropertyDeletable(dev, atom, FALSE);
+ return atom;
+}
+
void InitWcmDeviceProperties(InputInfoPtr pInfo)
{
WacomDevicePtr priv = (WacomDevicePtr) pInfo->private;
WacomCommonPtr common = priv->common;
int values[WCM_MAX_BUTTONS];
+ float fvalues[20];
int i;
DBG(10, priv, "\n");
@@ -227,6 +246,23 @@ void InitWcmDeviceProperties(InputInfoPtr pInfo)
prop_tablet_area = InitWcmAtom(pInfo->dev, WACOM_PROP_TABLET_AREA, XA_INTEGER, 32, 4, values);
}
+ if (!IsPad(priv)) {
+ float_type = XIGetKnownProperty(XATOM_FLOAT);
+ if (!float_type) float_type = MakeAtom(XATOM_FLOAT, strlen(XATOM_FLOAT), TRUE);
+
+ if (float_type) {
+ // topX, topY, bottomX, bottomY
+ for (i = 0; i < 4; ++i) {
+ fvalues[i*5+0] = 0.0; // border
+ fvalues[i*5+1] = 0.0; // x^3
+ fvalues[i*5+2] = 0.0; // x^2
+ fvalues[i*5+3] = 1.0; // x
+ fvalues[i*5+4] = 0.0; // 1
+ }
+ prop_distortion = InitFloatAtom(pInfo->dev, WACOM_PROP_TABLET_DISTORTION, 20, fvalues);
+ }
+ }
+
values[0] = common->wcmRotate;
if (!IsPad(priv)) {
prop_rotation = InitWcmAtom(pInfo->dev, WACOM_PROP_ROTATION, XA_INTEGER, 8, 1, values);
@@ -683,6 +719,15 @@ int wcmDeleteProperty(DeviceIntPtr dev, Atom property)
return (i >= 0) ? BadAccess : Success;
}
+static void setDistortionProperty(float* values, float *border, float *polynomial)
+{
+ *border = values[0]; // border width relatively to the screen dimension
+ polynomial[0] = values[1]; // x^3 coefficient of the polynomial
+ polynomial[1] = values[2]; // x^2 coefficient
+ polynomial[2] = values[3]; // x coefficient
+ polynomial[3] = values[4]; // constant coefficient
+}
+
int wcmSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
BOOL checkonly)
{
@@ -717,6 +762,20 @@ int wcmSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
priv->bottomX = values[2];
priv->bottomY = values[3];
}
+ } else if (property == prop_distortion)
+ {
+ float *values = (float*)prop->data;
+
+ if (prop->size != 20 || prop->format != 32 || prop->type != float_type)
+ return BadValue;
+
+ if (!checkonly)
+ {
+ setDistortionProperty(values, &priv->distortion_topX_border, priv->distortion_topX_poly);
+ setDistortionProperty(values+5, &priv->distortion_topY_border, priv->distortion_topY_poly);
+ setDistortionProperty(values+10, &priv->distortion_bottomX_border, priv->distortion_bottomX_poly);
+ setDistortionProperty(values+15, &priv->distortion_bottomY_border, priv->distortion_bottomY_poly);
+ }
} else if (property == prop_pressurecurve)
{
INT32 *pcurve;
diff --git src/xf86WacomDefs.h src/xf86WacomDefs.h
index 1575960..2d76514 100644
--- src/xf86WacomDefs.h
+++ src/xf86WacomDefs.h
@@ -262,6 +262,16 @@ struct _WacomDeviceRec
unsigned int cur_serial; /* current serial in prox */
int cur_device_id; /* current device ID in prox */
+ /* distortion */
+ float distortion_topX_border;
+ float distortion_topY_border;
+ float distortion_bottomX_border;
+ float distortion_bottomY_border;
+ float distortion_topX_poly[4];
+ float distortion_topY_poly[4];
+ float distortion_bottomX_poly[4];
+ float distortion_bottomY_poly[4];
+
/* button mapping information
*
* 'button' variables are indexed by physical button number (0..nbuttons)
------------------------------------------------------------------------------
_______________________________________________
Linuxwacom-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel