• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

A generic touchscreen calibration program for X.Org


Commit MetaInfo

Revisión084adde93435e7f74e0dfdded5a5bb0ba4ae90a0 (tree)
Tiempo2012-06-19 06:36:45
AutorTias Guns <tias@ulys...>
CommiterTias Guns

Log Message

Merge branch 'tester'

A tester object to faithfully test the calibration routines.
This will be reused for testing the evdev calibration (which
is non-standard) as well.

Cambiar Resumen

Diferencia incremental

--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,7 +30,7 @@ SUBDIRS = \
3030
3131 AM_CXXFLAGS = -Wall -ansi -pedantic
3232
33-bin_PROGRAMS = xinput_calibrator
33+bin_PROGRAMS = xinput_calibrator tester
3434
3535 COMMON_SRCS=calibrator.cpp calibrator/XorgPrint.cpp calibrator/Evdev.cpp calibrator/Usbtouchscreen.cpp main_common.cpp
3636
@@ -51,6 +51,10 @@ xinput_calibrator_CXXFLAGS = $(XINPUT_CFLAGS) $(GTKMM_CFLAGS) $(AM_CXXFLAGS)
5151 xinput_calibrator_LDFLAGS = -Wl,--as-needed
5252 endif
5353
54+tester_SOURCES = tester.cpp calibrator.cpp calibrator/Tester.cpp
55+tester_LDADD = $(XINPUT_LIBS) $(XRANDR_LIBS) $(X11_LIBS)
56+tester_CXXFLAGS = $(XINPUT_CFLAGS) $(X11_CFLAGS) $(XRANDR_CFLAGS) $(AM_CXXFLAGS)
57+
5458 EXTRA_DIST = \
5559 calibrator.cpp \
5660 calibrator.hh \
--- a/src/calibrator.cpp
+++ b/src/calibrator.cpp
@@ -251,3 +251,71 @@ bool Calibrator::has_xorgconfd_support(Display* dpy) {
251251
252252 return has_support;
253253 }
254+
255+/*
256+ * FROM xf86Xinput.c
257+ *
258+ * Cx - raw data from touch screen
259+ * to_max - scaled highest dimension
260+ * (remember, this is of rows - 1 because of 0 origin)
261+ * to_min - scaled lowest dimension
262+ * from_max - highest raw value from touch screen calibration
263+ * from_min - lowest raw value from touch screen calibration
264+ *
265+ * This function is the same for X or Y coordinates.
266+ * You may have to reverse the high and low values to compensate for
267+ * different orgins on the touch screen vs X.
268+ *
269+ * e.g. to scale from device coordinates into screen coordinates, call
270+ * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max);
271+ */
272+int
273+xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min)
274+{
275+ int X;
276+ int64_t to_width = to_max - to_min;
277+ int64_t from_width = from_max - from_min;
278+
279+ if (from_width) {
280+ X = (int) (((to_width * (Cx - from_min)) / from_width) + to_min);
281+ }
282+ else {
283+ X = 0;
284+ printf("Divide by Zero in xf86ScaleAxis\n");
285+ exit(1);
286+ }
287+
288+ if (X > to_max)
289+ X = to_max;
290+ if (X < to_min)
291+ X = to_min;
292+
293+ return X;
294+}
295+
296+// same but without rounding to min/max
297+int
298+scaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min)
299+{
300+ int X;
301+ int64_t to_width = to_max - to_min;
302+ int64_t from_width = from_max - from_min;
303+
304+ if (from_width) {
305+ X = (int) (((to_width * (Cx - from_min)) / from_width) + to_min);
306+ }
307+ else {
308+ X = 0;
309+ printf("Divide by Zero in scaleAxis\n");
310+ exit(1);
311+ }
312+
313+ /* no rounding to max/min
314+ if (X > to_max)
315+ X = to_max;
316+ if (X < to_min)
317+ X = to_min;
318+ */
319+
320+ return X;
321+}
--- a/src/calibrator.hh
+++ b/src/calibrator.hh
@@ -27,8 +27,12 @@
2727
2828 #include <stdexcept>
2929 #include <X11/Xlib.h>
30+#include <stdio.h>
3031 #include <vector>
3132
33+int xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min);
34+int scaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min);
35+
3236 /*
3337 * Number of blocks. We partition the screen into 'num_blocks' x 'num_blocks'
3438 * rectangles of equal size. We then ask the user to press points that are
@@ -91,6 +95,18 @@ struct XYinfo {
9195 void do_swap_xy() {
9296 swap_xy = !swap_xy;
9397 }
98+
99+ void do_xf86ScaleAxis(XYinfo& to, XYinfo& from) {
100+ x.min = xf86ScaleAxis(x.min, to.x.max, to.x.min, from.x.max, from.x.min);
101+ x.max = xf86ScaleAxis(x.max, to.x.max, to.x.min, from.x.max, from.x.min);
102+ y.min = xf86ScaleAxis(y.min, to.y.max, to.y.min, from.y.max, from.y.min);
103+ y.max = xf86ScaleAxis(y.max, to.y.max, to.y.min, from.y.max, from.y.min);
104+ }
105+
106+ void print(const char* xtra="\n") {
107+ printf("XYinfo: x.min=%i, x.max=%i, y.min=%i, y.max=%i, swap_xy=%i, invert_x=%i, invert_y=%i%s",
108+ x.min, x.max, y.min, y.max, swap_xy, x.invert, y.invert, xtra);
109+ }
94110 };
95111
96112 /// Names of the points
--- a/src/calibrator/Makefile.am
+++ b/src/calibrator/Makefile.am
@@ -1,4 +1,5 @@
11 EXTRA_DIST = \
22 Evdev.cpp \
33 Usbtouchscreen.cpp \
4- XorgPrint.cpp
4+ XorgPrint.cpp \
5+ Tester.cpp
--- /dev/null
+++ b/src/calibrator/Tester.cpp
@@ -0,0 +1,72 @@
1+/*
2+ * Copyright (c) 2009 Tias Guns
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#include "calibrator/Tester.hpp"
24+
25+#include <cstdio>
26+
27+CalibratorTester::CalibratorTester(const char* const device_name0, const XYinfo& axys0, const int thr_misclick, const int thr_doubleclick, const OutputType output_type, const char* geometry)
28+ : Calibrator(device_name0, axys0, thr_misclick, thr_doubleclick, output_type, geometry)
29+{
30+ //printf("Starting test driver\n");
31+}
32+
33+bool CalibratorTester::finish_data(const XYinfo axis)
34+{
35+ new_axis = axis;
36+
37+ return true;
38+}
39+
40+XYinfo CalibratorTester::emulate_driver(XYinfo& raw, bool useNewAxis, XYinfo screen, XYinfo device) {
41+ XYinfo calibAxis;
42+ if (useNewAxis)
43+ calibAxis = new_axis;
44+ else
45+ calibAxis = old_axys;
46+
47+ /**
48+ * The most simple and intuitive calibration implementation
49+ * if only all drivers sticked to this...
50+ * Note that axis inversion is automatically supported
51+ * by the ScaleAxis implementation (swapping max/min on
52+ * one axis will result in the inversion being calculated)
53+ */
54+
55+ // placeholder for the new coordinates
56+ XYinfo result(raw);
57+
58+ // swap coordinates if asked
59+ if (calibAxis.swap_xy) {
60+ result.x.min = raw.y.min;
61+ result.x.max = raw.y.max;
62+ result.y.min = raw.x.min;
63+ result.y.max = raw.x.max;
64+ }
65+
66+ result.do_xf86ScaleAxis(device, calibAxis);
67+
68+ // the last step is usually done by the X server,
69+ // or transparently somewhere on the way
70+ result.do_xf86ScaleAxis(screen, device);
71+ return result;
72+}
--- /dev/null
+++ b/src/calibrator/Tester.hpp
@@ -0,0 +1,53 @@
1+/*
2+ * Copyright (c) 2009 Tias Guns
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#ifndef CALIBRATOR_TESTER_HPP
24+#define CALIBRATOR_TESTER_HPP
25+
26+#include "calibrator.hh"
27+
28+/***************************************
29+ * Class for generic Xorg driver,
30+ * outputs new Xorg.conf and FDI policy, on stdout
31+ ***************************************/
32+class CalibratorTester: public Calibrator
33+{
34+protected:
35+ // store the new axis for use in driver emulation
36+ XYinfo new_axis;
37+
38+public:
39+ CalibratorTester(const char* const device_name, const XYinfo& axys,
40+ const int thr_misclick=0, const int thr_doubleclick=0,
41+ const OutputType output_type=OUTYPE_AUTO, const char* geometry=0);
42+
43+ virtual bool finish_data(const XYinfo new_axis);
44+
45+ // emulate the driver processing the coordinates in 'raw'
46+ XYinfo emulate_driver(XYinfo& raw, bool useNewAxis, XYinfo screen, XYinfo device);
47+
48+ void new_axis_print() {
49+ new_axis.print();
50+ }
51+};
52+
53+#endif
--- /dev/null
+++ b/src/tester.cpp
@@ -0,0 +1,105 @@
1+#include <algorithm>
2+#include <stdio.h>
3+#include <vector>
4+
5+#include "calibrator.hh"
6+#include "calibrator/Tester.hpp"
7+
8+int main() {
9+ // screen dimensions
10+ int width = 800;
11+ int height = 600;
12+ XYinfo screen_res(0, width, 0, height);
13+
14+ int delta_x = width/(float)num_blocks;
15+ int delta_y = height/(float)num_blocks;
16+ XYinfo target(delta_x, width-delta_x, delta_y, height-delta_y);
17+
18+ int slack = 2; // amount of pixels result can be off target
19+
20+ XYinfo dev_res(0, 1000, 0, 1000);
21+
22+ std::vector<XYinfo> old_axes;
23+ old_axes.push_back( XYinfo(0, 1000, 0, 1000) );
24+ old_axes.push_back( XYinfo(1000, 0, 0, 1000) );
25+ old_axes.push_back( XYinfo(0, 1000, 1000, 0) );
26+ old_axes.push_back( XYinfo(1000, 0, 0, 1000) );
27+ old_axes.push_back( XYinfo(0, 1000, 0, 1000, 1, 0, 0) );
28+ old_axes.push_back( XYinfo(0, 1000, 0, 1000, 1, 0, 1) );
29+ old_axes.push_back( XYinfo(0, 1000, 0, 1000, 1, 1, 0) );
30+ old_axes.push_back( XYinfo(0, 1000, 0, 1000, 1, 1, 1) );
31+ old_axes.push_back( XYinfo(1000, 0, 0, 1000, 1, 0, 0) );
32+ old_axes.push_back( XYinfo(1000, 0, 0, 1000, 1, 0, 1) );
33+ old_axes.push_back( XYinfo(1000, 0, 0, 1000, 1, 1, 0) );
34+ old_axes.push_back( XYinfo(1000, 0, 0, 1000, 1, 1, 1) );
35+ // non device-resolution calibs
36+ old_axes.push_back( XYinfo(42, 929, 20, 888) );
37+ // xf86ScaleAxis rounds to min/max, this can lead to inaccurate
38+ // results! Can we fix that?
39+ old_axes.push_back( XYinfo(42, 929, 20, 888) );
40+ //old_axes.push_back( XYinfo(-9, 895, 124, 990) ); // this is the true axis
41+ // rounding error when raw_coords are swapped???
42+ //old_axes.push_back( XYinfo(75, 750, 20, 888) ); // rounding error on X axis
43+ //old_axes.push_back( XYinfo(42, 929, 120, 888) ); // rounding error on Y axis
44+
45+ // raw device coordinates to emulate
46+ std::vector<XYinfo> raw_coords;
47+ // normal
48+ raw_coords.push_back( XYinfo(105, 783, 233, 883) );
49+ // invert x, y, x+y
50+ raw_coords.push_back( XYinfo(783, 105, 233, 883) );
51+ raw_coords.push_back( XYinfo(105, 783, 883, 233) );
52+ raw_coords.push_back( XYinfo(783, 105, 883, 233) );
53+ // swap
54+ raw_coords.push_back( XYinfo(233, 883, 105, 783) );
55+ // swap and inverts
56+ raw_coords.push_back( XYinfo(233, 883, 783, 105) );
57+ raw_coords.push_back( XYinfo(883, 233, 105, 783) );
58+ raw_coords.push_back( XYinfo(883, 233, 783, 105) );
59+
60+ for (unsigned a=0; a != old_axes.size(); a++) {
61+ XYinfo old_axis(old_axes[a]);
62+ printf("Old axis: "); old_axis.print();
63+
64+ for (unsigned c=0; c != raw_coords.size(); c++) {
65+ XYinfo raw(raw_coords[c]);
66+ //printf("Raw: "); raw.print();
67+
68+ CalibratorTester calib("Tester", old_axis);
69+
70+ // clicked from raw
71+ XYinfo clicked = calib.emulate_driver(raw, false, screen_res, dev_res);// false=old_axis
72+ //printf("\tClicked: "); clicked.print();
73+
74+ // emulate screen clicks
75+ calib.add_click(clicked.x.min, clicked.y.min);
76+ calib.add_click(clicked.x.max, clicked.y.min);
77+ calib.add_click(clicked.x.min, clicked.y.max);
78+ calib.add_click(clicked.x.max, clicked.y.max);
79+ calib.finish(width, height);
80+
81+ // test result
82+ XYinfo result = calib.emulate_driver(raw, true, screen_res, dev_res); // true=new_axis
83+
84+ int maxdiff = std::max(abs(target.x.min - result.x.min),
85+ std::max(abs(target.x.max - result.x.max),
86+ std::max(abs(target.y.min - result.y.min),
87+ abs(target.y.max - result.y.max)))); // no n-ary max in c++??
88+ if (maxdiff > slack) {
89+ printf("-\n");
90+ printf("Old axis: "); old_axis.print();
91+ printf("Raw: "); raw.print();
92+ printf("Clicked: "); clicked.print();
93+ printf("New axis: "); calib.new_axis_print();
94+ printf("Error: difference between target and result: %i > %i:\n", maxdiff, slack);
95+ printf("\tTarget: "); target.print();
96+ printf("\tResult: "); result.print();
97+ exit(1);
98+ }
99+
100+ printf("%i", maxdiff);
101+ } // loop over raw_coords
102+
103+ printf(". OK\n");
104+ } // loop over old_axes
105+}