eflxx/examples/angstrom/bootmanager/calibrate.cpp

302 lines
9.8 KiB
C++

#include "calibrate.h"
#include <cstdio>
#include <cerrno>
using namespace std;
#include <eflpp_evas.h>
#include <eflpp_ecore.h>
#ifdef ENABLE_EFLPP_FB
#include <Ecore_Fb.h>
#endif
#include <Ecore.h>
const unsigned int offset = 32;
static Ecore_Event_Filter* filter = 0;
static void* calibration_event_filter_start( void* data )
{
return 0;
}
static int calibration_event_filter_event( void* loop_data, void *data, int type, void* event )
{
#ifdef ENABLE_EFLPP_FB
if ( type == ECORE_FB_EVENT_MOUSE_BUTTON_UP )
{
Ecore_Fb_Event_Mouse_Button_Up* ev = static_cast<Ecore_Fb_Event_Mouse_Button_Up*>( event );
cout << " - data = " << data << endl;
cout << " - mouse button up at position = " << ev->x << ", " << ev->y << endl;
CalibrationRectangle* cr = reinterpret_cast<CalibrationRectangle*>( data );
cr->nextPoint( ev->x, ev->y );
return 0; // swallow event
}
else
#endif
{
return 1; // keep event
}
}
static void calibration_event_filter_end( void* data, void *loop_data )
{
}
CalibrationRectangle::CalibrationRectangle( int x, int y, int width, int height, EvasCanvas* evas )
:EvasRectangle( x, y, width, height, evas, "CalibrationRectangle" )
{
setLayer( 255 );
setColor( 255, 255, 255, 0 ); // white, fully transparent
// setup the five calibration points
Size s = evas->size();
cd.canvasPoints[TopLeft].set( offset, offset );
cd.canvasPoints[BottomLeft].set( offset, s.height()-offset );
cd.canvasPoints[BottomRight].set( s.width()-offset, s.height()-offset );
cd.canvasPoints[TopRight].set( s.width()-offset, offset );
cd.canvasPoints[Center].set( s.width()/2, s.height()/2 );
switch ( eApp->mainWindow()->rotation() )
{
case 0:
cout << "ROT 0" << endl;
cd.screenPoints[TopLeft] = cd.canvasPoints[TopLeft];
cd.screenPoints[BottomLeft] = cd.canvasPoints[BottomLeft];
cd.screenPoints[BottomRight] = cd.canvasPoints[BottomRight];
cd.screenPoints[TopRight] = cd.canvasPoints[TopRight];
cd.screenPoints[Center] = cd.canvasPoints[Center];
break;
case 90:
cd.screenPoints[TopLeft] = cd.canvasPoints[TopLeft];
cd.screenPoints[BottomLeft] = cd.canvasPoints[BottomLeft];
cd.screenPoints[BottomRight] = cd.canvasPoints[BottomRight];
cd.screenPoints[TopRight] = cd.canvasPoints[TopRight];
cd.screenPoints[Center] = cd.canvasPoints[Center];
break;
case 180:
cd.screenPoints[TopLeft] = cd.canvasPoints[TopLeft];
cd.screenPoints[BottomLeft] = cd.canvasPoints[BottomLeft];
cd.screenPoints[BottomRight] = cd.canvasPoints[BottomRight];
cd.screenPoints[TopRight] = cd.canvasPoints[TopRight];
cd.screenPoints[Center] = cd.canvasPoints[Center];
break;
case 270:
cout << "ROT 270" << endl;
cd.screenPoints[TopLeft].set( s.height()-offset, offset );
cd.screenPoints[BottomLeft].set( offset, offset );
cd.screenPoints[BottomRight].set( offset, s.width()-offset );
cd.screenPoints[TopRight].set( s.height()-offset, s.width()-offset );
cd.screenPoints[Center].set( s.height()/2, s.width()/2 );
break;
}
// setup background
background = new EvasGradient( 0, 0, s.width(), s.height(), evas );
background->setLayer( 21 );
background->setAngle( 15 );
background->addColor( 255, 255, 255, 255, 10 );
background->addColor( 200, 200, 200, 255, 10 );
background->addColor( 255, 255, 255, 255, 10 );
background->show();
// setup text
text = new EvasText( PACKAGE_DATA_DIR "/fonts/Vera.ttf", 12, 0, s.height()/2, "foo", evas );
text->setColor( 0, 0, 0, 255 );
text->setLayer( 22 );
text->setText( "Click on crosshair to calibrate screen" );
text->show();
// setup crosshair
#if 0
crosshair = new EvasImage( PACKAGE_DATA_DIR "/images/crosshair.png", evas );
crosshair->setLayer( 23 );
#else
crosshairhorz = new EvasLine( evas );
crosshairvert = new EvasLine( evas );
crosshairhorz->setLayer( 23 );
crosshairvert->setLayer( 23 );
crosshairhorz->setColor( 0, 0, 0, 255 );
crosshairvert->setColor( 0, 0, 0, 255 );
crosshairhorz->show();
crosshairvert->show();
#endif
}
CalibrationRectangle::~CalibrationRectangle()
{
}
bool CalibrationRectangle::handleShow()
{
#ifdef ENABLE_EFLPP_FB
ecore_fb_touch_screen_calibrate_set( 1, 0, 0, 0, 0 );
#endif
cout << "this = " << this << endl;
filter = ecore_event_filter_add( &calibration_event_filter_start,
&calibration_event_filter_event,
&calibration_event_filter_end, this );
position = TopLeft;
moveCrossHair();
}
void CalibrationRectangle::nextPoint( int x, int y )
{
cd.devicePoints[position].set( x, y );
if ( ++position <= LastPosition )
{
moveCrossHair();
}
else
{
//FIXME: Don't delete or hide, dissolve, and after that, hide :D
//hide();
hide();
delete background;
#if 0
delete crosshair;
#else
delete crosshairhorz;
delete crosshairvert;
#endif
delete text;
//crosshair->hide();
//text->hide();
#ifdef ENABLE_EFLPP_FB
ecore_fb_touch_screen_calibrate_set( 0, 0, 0, 0, 0 );
#endif
ecore_event_filter_del( filter );
calibrate();
done.emit();
}
}
void CalibrationRectangle::moveCrossHair()
{
#if 0
crosshair->move( cd.canvasPoints[position] );
crosshair->show();
#else
int x = cd.canvasPoints[position].x();
int y = cd.canvasPoints[position].y();
crosshairhorz->setGeometry( x-offset/2, y, offset, 0 );
crosshairvert->setGeometry( x, y-offset/2, 0, offset );
#endif
}
bool CalibrationRectangle::calibrate()
{
// calibration code based on ts_calibrate.c (C) Russell King
int j;
float n, x, y, x2, y2, xy, z, zx, zy;
float det, cal_a, cal_b, cal_c, cal_d, cal_e, cal_f, cal_i;
float scaling = 65536.0;
int cal_x[5], cal_xfb[5], cal_y[5], cal_yfb[5], cal_o[7];
cal_x[0]=cd.devicePoints[ TopLeft ].x();
cal_y[0]=cd.devicePoints[ TopLeft ].y();
cal_x[1]=cd.devicePoints[ TopRight ].x();
cal_y[1]=cd.devicePoints[ TopRight ].y();
cal_x[2]=cd.devicePoints[ BottomLeft ].x();
cal_y[2]=cd.devicePoints[ BottomLeft ].y();
cal_x[3]=cd.devicePoints[ BottomRight ].x();
cal_y[3]=cd.devicePoints[ BottomRight ].y();
cal_x[4]=cd.devicePoints[ Center ].x();
cal_y[4]=cd.devicePoints[ Center ].y();
cal_xfb[0]=cd.screenPoints[ TopLeft ].x();
cal_yfb[0]=cd.screenPoints[ TopLeft ].y();
cal_xfb[1]=cd.screenPoints[ TopRight ].x();
cal_yfb[1]=cd.screenPoints[ TopRight ].y();
cal_xfb[2]=cd.screenPoints[ BottomLeft ].x();
cal_yfb[2]=cd.screenPoints[ BottomLeft ].y();
cal_xfb[3]=cd.screenPoints[ BottomRight ].x();
cal_yfb[3]=cd.screenPoints[ BottomRight ].y();
cal_xfb[4]=cd.screenPoints[ Center ].x();
cal_yfb[4]=cd.screenPoints[ Center ].y();
// Get sums for matrix
n = x = y = x2 = y2 = xy = 0;
for(j=0;j<5;j++) {
n += 1.0;
x += (float)cal_x[j];
y += (float)cal_y[j];
x2 += (float)(cal_x[j]*cal_x[j]);
y2 += (float)(cal_y[j]*cal_y[j]);
xy += (float)(cal_x[j]*cal_y[j]);
}
// Get determinant of matrix -- check if determinant is too small
det = n*(x2*y2 - xy*xy) + x*(xy*y - x*y2) + y*(x*xy - y*x2);
if ( det < 0.1 && det > -0.1 )
{
cout << "CalibrationRectangle::calibrate() - determinant " << det << " is too small - aborting." << endl;
return false;
}
// Get elements of inverse matrix
cal_a = (x2*y2 - xy*xy)/det;
cal_b = (xy*y - x*y2)/det;
cal_c = (x*xy - y*x2)/det;
cal_e = (n*y2 - y*y)/det;
cal_f = (x*y - n*xy)/det;
cal_i = (n*x2 - x*x)/det;
// Get sums for x calibration
z = zx = zy = 0;
for( j=0; j < 5; j++ ) {
z += (float)cal_xfb[j];
zx += (float)(cal_xfb[j]*cal_x[j]);
zy += (float)(cal_xfb[j]*cal_y[j]);
}
// Now multiply out to get the calibration for framebuffer x coord
cal_o[0] = (int)((cal_a*z + cal_b*zx + cal_c*zy)*(scaling));
cal_o[1] = (int)((cal_b*z + cal_e*zx + cal_f*zy)*(scaling));
cal_o[2] = (int)((cal_c*z + cal_f*zx + cal_i*zy)*(scaling));
cout << "CAL: " << (cal_a*z + cal_b*zx + cal_c*zy) << " "
<< (cal_b*z + cal_e*zx + cal_f*zy) << " "
<< (cal_c*z + cal_f*zx + cal_i*zy) << endl;
// Get sums for y calibration
z = zx = zy = 0;
for (j=0;j<5;j++) {
z += (float)cal_yfb[j];
zx += (float)(cal_yfb[j]*cal_x[j]);
zy += (float)(cal_yfb[j]*cal_y[j]);
}
// Now multiply out to get the calibration for framebuffer y coord
cal_o[3] = (int)((cal_a*z + cal_b*zx + cal_c*zy)*(scaling));
cal_o[4] = (int)((cal_b*z + cal_e*zx + cal_f*zy)*(scaling));
cal_o[5] = (int)((cal_c*z + cal_f*zx + cal_i*zy)*(scaling));
cout << "CAL: " << (cal_a*z + cal_b*zx + cal_c*zy) << " "
<< (cal_b*z + cal_e*zx + cal_f*zy) << " "
<< (cal_c*z + cal_f*zx + cal_i*zy) << endl;
// If we got here, we're OK, so assign scaling to a[6] and return
cal_o[6] = (int) scaling;
cout << "CAL constants: " << cal_o[0] << " " << cal_o[1] << " " << cal_o[2] << " "
<< cal_o[3] << " " << cal_o[4] << " " << cal_o[5] << " " << cal_o[6] << endl;
FILE* stream = fopen( "/etc/pointercal", "w" );
if ( stream == NULL )
{
cout << "CalibrationRectangle::calibrate() - couldn't open /etc/pointercal (" << strerror( errno ) << ")" << endl;
return false;
}
fprintf( stream, "%d %d %d %d %d %d %d\n", cal_o[1], cal_o[2], cal_o[0], cal_o[4], cal_o[5], cal_o[3], cal_o[6] );
fclose( stream );
return true;
}