/tools/qvfb/qvfbview.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 883 lines · 729 code · 98 blank · 56 comment · 108 complexity · 68352e79770abcf96a1931e6b97c3333 MD5 · raw file

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  4. ** All rights reserved.
  5. ** Contact: Nokia Corporation (qt-info@nokia.com)
  6. **
  7. ** This file is part of the tools applications of the Qt Toolkit.
  8. **
  9. ** $QT_BEGIN_LICENSE:LGPL$
  10. ** GNU Lesser General Public License Usage
  11. ** This file may be used under the terms of the GNU Lesser General Public
  12. ** License version 2.1 as published by the Free Software Foundation and
  13. ** appearing in the file LICENSE.LGPL included in the packaging of this
  14. ** file. Please review the following information to ensure the GNU Lesser
  15. ** General Public License version 2.1 requirements will be met:
  16. ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  17. **
  18. ** In addition, as a special exception, Nokia gives you certain additional
  19. ** rights. These rights are described in the Nokia Qt LGPL Exception
  20. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  21. **
  22. ** GNU General Public License Usage
  23. ** Alternatively, this file may be used under the terms of the GNU General
  24. ** Public License version 3.0 as published by the Free Software Foundation
  25. ** and appearing in the file LICENSE.GPL included in the packaging of this
  26. ** file. Please review the following information to ensure the GNU General
  27. ** Public License version 3.0 requirements will be met:
  28. ** http://www.gnu.org/copyleft/gpl.html.
  29. **
  30. ** Other Usage
  31. ** Alternatively, this file may be used in accordance with the terms and
  32. ** conditions contained in a signed written agreement between you and Nokia.
  33. **
  34. **
  35. **
  36. **
  37. **
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. #include "qvfbview.h"
  42. #include "qvfbshmem.h"
  43. #include "qvfbmmap.h"
  44. #include "qanimationwriter.h"
  45. #include <QApplication>
  46. #include <QPainter>
  47. #include <QImage>
  48. #include <QBitmap>
  49. #include <QMatrix>
  50. #include <QPaintEvent>
  51. #include <QScrollArea>
  52. #include <QFile>
  53. #include <QDebug>
  54. #ifdef Q_WS_X11
  55. #include <QX11EmbedContainer>
  56. #include <QHBoxLayout>
  57. #endif
  58. #include <stdlib.h>
  59. #include <unistd.h>
  60. #include <sys/types.h>
  61. #include <errno.h>
  62. #include <math.h>
  63. QT_BEGIN_NAMESPACE
  64. extern int qvfb_protocol;
  65. QVFbAbstractView::QVFbAbstractView( QWidget *parent )
  66. #ifdef QVFB_USE_GLWIDGET
  67. : QGLWidget( parent )
  68. #else
  69. : QWidget( parent )
  70. #endif
  71. {
  72. }
  73. QVFbAbstractView::~QVFbAbstractView()
  74. {
  75. }
  76. QVFbView::QVFbView(int id, int w, int h, int d, Rotation r, QWidget *parent)
  77. : QVFbAbstractView(parent),
  78. viewdepth(d), viewFormat(DefaultFormat), rgb_swapped(0), rsh(0), gsh(0), bsh(0), rmax(15), gmax(15), bmax(15),
  79. contentsWidth(w), contentsHeight(h), gred(1.0), ggreen(1.0), gblue(1.0),
  80. gammatable(0), refreshRate(30), animation(0),
  81. hzm(0.0), vzm(0.0), mView(0),
  82. emulateTouchscreen(false), emulateLcdScreen(false), rotation(r)
  83. #ifdef Q_WS_X11
  84. , embedContainer(0)
  85. #endif
  86. {
  87. switch(qvfb_protocol) {
  88. default:
  89. case 0:
  90. mView = new QShMemViewProtocol(id, QSize(w, h), d, this);
  91. break;
  92. case 1:
  93. mView = new QMMapViewProtocol(id, QSize(w, h), d, this);
  94. break;
  95. }
  96. connect(mView, SIGNAL(displayDataChanged(QRect)),
  97. SLOT(refreshDisplay(QRect)));
  98. #ifdef Q_WS_X11
  99. connect(mView, SIGNAL(displayEmbedRequested(WId)),
  100. this, SLOT(embedDisplay(WId)));
  101. #endif
  102. setAttribute(Qt::WA_PaintOnScreen, viewFormat != ARGBFormat);
  103. setMouseTracking(true);
  104. setFocusPolicy(Qt::StrongFocus);
  105. setAttribute(Qt::WA_NoSystemBackground);
  106. setZoom(1.0,1.0);
  107. setGamma(1.0,1.0,1.0);
  108. mView->setRate(30);
  109. }
  110. QVFbView::~QVFbView()
  111. {
  112. stopAnimation();
  113. sendKeyboardData(0, 0, 0, true, false); // magic die key
  114. #ifdef Q_WS_X11
  115. delete embedContainer;
  116. #endif
  117. }
  118. QSize QVFbView::sizeHint() const
  119. {
  120. return QSize(contentsWidth, contentsHeight);
  121. }
  122. void QVFbView::setRate(int i)
  123. {
  124. mView->setRate(i);
  125. }
  126. void QVFbView::setGamma(double gr, double gg, double gb)
  127. {
  128. gred = gr; ggreen = gg; gblue = gb;
  129. switch (viewdepth) {
  130. case 12:
  131. rsh = 12;
  132. gsh = 7;
  133. bsh = 1;
  134. rmax = 15;
  135. gmax = 15;
  136. bmax = 15;
  137. break;
  138. case 15:
  139. rsh = 10;
  140. gsh = 5;
  141. bsh = 0;
  142. rmax = 31;
  143. gmax = 31;
  144. bmax = 31;
  145. break;
  146. case 16:
  147. rsh = 11;
  148. gsh = 5;
  149. bsh = 0;
  150. rmax = 31;
  151. gmax = 63;
  152. bmax = 31;
  153. break;
  154. case 18:
  155. rsh = 12;
  156. gsh = 6;
  157. bsh = 0;
  158. rmax = 63;
  159. gmax = 63;
  160. bmax = 63;
  161. break;
  162. case 24:
  163. case 32:
  164. rsh = 16;
  165. gsh = 8;
  166. bsh = 0;
  167. rmax = 255;
  168. gmax = 255;
  169. bmax = 255;
  170. }
  171. int mm = qMax(rmax,qMax(gmax,bmax))+1;
  172. if (gammatable)
  173. delete [] gammatable;
  174. gammatable = new QRgb[mm];
  175. for (int i=0; i<mm; i++) {
  176. int r = int(pow(i,gr)*255/rmax);
  177. int g = int(pow(i,gg)*255/gmax);
  178. int b = int(pow(i,gb)*255/bmax);
  179. if (r > 255) r = 255;
  180. if (g > 255) g = 255;
  181. if (b > 255) b = 255;
  182. gammatable[i] = qRgb(r,g,b);
  183. //qDebug("%d: %d,%d,%d",i,r,g,b);
  184. }
  185. mView->flushChanges();
  186. }
  187. void QVFbView::getGamma(int i, QRgb& rgb)
  188. {
  189. if (i > 255) i = 255;
  190. if (i < 0) i = 0;
  191. rgb = qRgb(qRed(gammatable[i*rmax/255]),
  192. qGreen(gammatable[i*rmax/255]),
  193. qBlue(gammatable[i*rmax/255]));
  194. }
  195. int QVFbView::displayId() const
  196. {
  197. return mView->id();
  198. }
  199. int QVFbView::displayWidth() const
  200. {
  201. return mView->width();
  202. }
  203. int QVFbView::displayHeight() const
  204. {
  205. return mView->height();
  206. }
  207. int QVFbView::displayDepth() const
  208. {
  209. return viewdepth;
  210. }
  211. QVFbView::PixelFormat QVFbView::displayFormat() const
  212. {
  213. return viewFormat;
  214. }
  215. QVFbView::Rotation QVFbView::displayRotation() const
  216. {
  217. return rotation;
  218. }
  219. void QVFbView::setZoom(double hz, double vz)
  220. {
  221. if (hzm != hz || vzm != vz) {
  222. hzm = hz;
  223. vzm = vz;
  224. mView->flushChanges();
  225. contentsWidth = int(displayWidth()*hz);
  226. contentsHeight = int(displayHeight()*vz);
  227. if (rotation & 1)
  228. qSwap(contentsWidth,contentsHeight);
  229. resize(contentsWidth, contentsHeight);
  230. if (isVisible()) {
  231. updateGeometry();
  232. qApp->sendPostedEvents();
  233. topLevelWidget()->adjustSize();
  234. update();
  235. }
  236. }
  237. }
  238. void QVFbView::setRotation(QVFbView::Rotation r)
  239. {
  240. rotation = r;
  241. // Force update...
  242. double ohzm = hzm;
  243. hzm=0.0;
  244. setZoom(ohzm,vzm);
  245. }
  246. static QRect mapToDevice(const QRect &r, const QSize &s, QVFbView::Rotation rotation)
  247. {
  248. int x1 = r.x();
  249. int y1 = r.y();
  250. int x2 = r.right();
  251. int y2 = r.bottom();
  252. int w = s.width();
  253. int h = s.height();
  254. switch (rotation) {
  255. case QVFbView::Rot90:
  256. return QRect(
  257. QPoint(y1, w - x1),
  258. QPoint(y2, w - x2)).normalized();
  259. case QVFbView::Rot180:
  260. return QRect(
  261. QPoint(w - x1, h - y1),
  262. QPoint(w - x2, h - y2)).normalized();
  263. case QVFbView::Rot270:
  264. return QRect(
  265. QPoint(h - y1, x1),
  266. QPoint(h - y2, x2)).normalized();
  267. default:
  268. break;
  269. }
  270. return r;
  271. }
  272. static QRect mapFromDevice(const QRect &r, const QSize &s, QVFbView::Rotation rotation)
  273. {
  274. return mapToDevice(r,s,QVFbView::Rotation(4-(int)rotation));
  275. }
  276. void QVFbView::sendMouseData(const QPoint &pos, int buttons, int wheel)
  277. {
  278. QPoint p = mapToDevice(QRect(pos,QSize(1,1)), QSize(int(width()/hzm), int(height()/vzm)), rotation).topLeft();
  279. mView->sendMouseData(p, buttons, wheel);
  280. }
  281. void QVFbView::sendKeyboardData(QString unicode, int keycode, int modifiers,
  282. bool press, bool repeat)
  283. {
  284. mView->sendKeyboardData(unicode, keycode, modifiers, press, repeat);
  285. }
  286. void QVFbView::refreshDisplay(const QRect &r)
  287. {
  288. if (animation) {
  289. if (r.isEmpty()) {
  290. animation->appendBlankFrame();
  291. } else {
  292. int l;
  293. QImage img = getBuffer(r, l);
  294. animation->appendFrame(img,QPoint(r.x(),r.y()));
  295. }
  296. }
  297. if (!r.isNull()) {
  298. if (hzm == 1.0 && vzm == 1.0) // hw: workaround for 4.3.1
  299. update(mapFromDevice(r, QSize(displayWidth(), displayHeight()), rotation));
  300. else
  301. update();
  302. }
  303. }
  304. static void dim(QRgb* rgb, int n, int brightness)
  305. {
  306. uchar* b = (uchar*)rgb;
  307. #if Q_BYTE_ORDER == Q_BIG_ENDIAN
  308. b++;
  309. #endif
  310. while (n--) {
  311. b[0] = (uint)b[0] * brightness / 255;
  312. b[1] = (uint)b[1] * brightness / 255;
  313. b[2] = (uint)b[2] * brightness / 255;
  314. b += 4;
  315. }
  316. }
  317. QImage QVFbView::getBuffer(const QRect &r, int &leading) const
  318. {
  319. const int brightness = mView->brightness();
  320. if ( brightness == 0 ) {
  321. QImage img(r.size(),QImage::Format_RGB32);
  322. img.fill(0);
  323. leading = 0;
  324. return img;
  325. }
  326. static QByteArray buffer;
  327. const int requiredSize = r.width() * r.height() * 4;
  328. QImage img;
  329. leading = 0;
  330. switch (viewdepth) {
  331. case 1: {
  332. if (requiredSize > buffer.size())
  333. buffer.resize(requiredSize);
  334. // XXX: hw: replace by drawhelper functionality
  335. const int pixelsPerByte = 8;
  336. quint8 *src = reinterpret_cast<quint8*>(mView->data())
  337. + r.y() * mView->linestep() + r.x() / pixelsPerByte;
  338. const int align = qMin(r.width(), (8 - (r.x() & 7)) & 7);
  339. const int doAlign = (align > 0 ? 1 : 0);
  340. const int tail = qMin(r.width(), (r.width() - align) & 7);
  341. const int doTail = (tail > 0 ? 1 : 0);
  342. const int width8 = (r.width() - align) / pixelsPerByte;
  343. const int stride = mView->linestep() - (width8 + doAlign);
  344. uchar *b = reinterpret_cast<uchar*>(buffer.data());
  345. img = QImage(b, r.width(), r.height(), QImage::Format_RGB32);
  346. for (int y = 0; y < r.height(); ++y) {
  347. quint32 *dest = reinterpret_cast<quint32*>(img.scanLine(y));
  348. quint8 c;
  349. if (doAlign) {
  350. switch (align) {
  351. case 7: c = ((*src & 0x40) >> 6) * 0xff;
  352. *dest++ = qRgb(c, c, c);
  353. case 6: c = ((*src & 0x20) >> 5) * 0xff;
  354. *dest++ = qRgb(c, c, c);
  355. case 5: c = ((*src & 0x10) >> 4) * 0xff;
  356. *dest++ = qRgb(c, c, c);
  357. case 4: c = ((*src & 0x08) >> 3) * 0xff;
  358. *dest++ = qRgb(c, c, c);
  359. case 3: c = ((*src & 0x04) >> 2) * 0xff;
  360. *dest++ = qRgb(c, c, c);
  361. case 2: c = ((*src & 0x02) >> 1) * 0xff;
  362. *dest++ = qRgb(c, c, c);
  363. case 1: c = ((*src & 0x01)) * 0xff;
  364. *dest++ = qRgb(c, c, c);
  365. }
  366. ++src;
  367. }
  368. for (int i = 0; i < width8; ++i) {
  369. c = ((*src & 0x80) >> 7) * 0xff;
  370. *dest++ = qRgb(c, c, c);
  371. c = ((*src & 0x40) >> 6) * 0xff;
  372. *dest++ = qRgb(c, c, c);
  373. c = ((*src & 0x20) >> 5) * 0xff;
  374. *dest++ = qRgb(c, c, c);
  375. c = ((*src & 0x10) >> 4) * 0xff;
  376. *dest++ = qRgb(c, c, c);
  377. c = ((*src & 0x08) >> 3) * 0xff;
  378. *dest++ = qRgb(c, c, c);
  379. c = ((*src & 0x04) >> 2) * 0xff;
  380. *dest++ = qRgb(c, c, c);
  381. c = ((*src & 0x02) >> 1) * 0xff;
  382. *dest++ = qRgb(c, c, c);
  383. c = ((*src & 0x01)) * 0xff;
  384. *dest++ = qRgb(c, c, c);
  385. ++src;
  386. }
  387. if (doTail) {
  388. switch (tail) {
  389. case 7: c = ((*src & 0x02) >> 1) * 0xff;
  390. dest[6] = qRgb(c, c, c);
  391. case 6: c = ((*src & 0x04) >> 2) * 0xff;
  392. dest[5] = qRgb(c, c, c);
  393. case 5: c = ((*src & 0x08) >> 3) * 0xff;
  394. dest[4] = qRgb(c, c, c);
  395. case 4: c = ((*src & 0x10) >> 4) * 0xff;
  396. dest[3] = qRgb(c, c, c);
  397. case 3: c = ((*src & 0x20) >> 5) * 0xff;
  398. dest[2] = qRgb(c, c, c);
  399. case 2: c = ((*src & 0x40) >> 6) * 0xff;
  400. dest[1] = qRgb(c, c, c);
  401. case 1: c = ((*src & 0x80) >> 7) * 0xff;
  402. dest[0] = qRgb(c, c, c);
  403. }
  404. }
  405. src += stride;
  406. }
  407. break;
  408. }
  409. case 2: {
  410. if (requiredSize > buffer.size())
  411. buffer.resize(requiredSize);
  412. // XXX: hw: replace by drawhelper functionality
  413. const int pixelsPerByte = 4;
  414. quint8 *src = reinterpret_cast<quint8*>(mView->data())
  415. + r.y() * mView->linestep() + r.x() / pixelsPerByte;
  416. const int align = qMin(r.width(), (4 - (r.x() & 3)) & 3);
  417. const int doAlign = (align > 0 ? 1 : 0);
  418. const int tail = qMin(r.width(), (r.width() - align) & 3);
  419. const int doTail = (tail > 0 ? 1 : 0);
  420. const int width8 = (r.width() - align) / pixelsPerByte;
  421. const int stride = mView->linestep() - (width8 + doAlign);
  422. uchar *b = reinterpret_cast<uchar*>(buffer.data());
  423. img = QImage(b, r.width(), r.height(), QImage::Format_RGB32);
  424. for (int y = 0; y < r.height(); ++y) {
  425. quint32 *dest = reinterpret_cast<quint32*>(img.scanLine(y));
  426. quint8 c;
  427. if (doAlign) {
  428. switch (align) {
  429. case 3: c = ((*src & 0x30) >> 4) * 0x55;
  430. *dest++ = qRgb(c, c, c);
  431. case 2: c = ((*src & 0x0c) >> 2) * 0x55;
  432. *dest++ = qRgb(c, c, c);
  433. case 1: c = ((*src & 0x03)) * 0x55;
  434. *dest++ = qRgb(c, c, c);
  435. }
  436. ++src;
  437. }
  438. for (int i = 0; i < width8; ++i) {
  439. c = ((*src & 0xc0) >> 6) * 0x55;
  440. *dest++ = qRgb(c, c, c);
  441. c = ((*src & 0x30) >> 4) * 0x55;
  442. *dest++ = qRgb(c, c, c);
  443. c = ((*src & 0x0c) >> 2) * 0x55;
  444. *dest++ = qRgb(c, c, c);
  445. c = ((*src & 0x03)) * 0x55;
  446. *dest++ = qRgb(c, c, c);
  447. ++src;
  448. }
  449. if (doTail) {
  450. switch (tail) {
  451. case 3: c = ((*src & 0x0c) >> 2) * 0x55;
  452. dest[2] = qRgb(c, c, c);
  453. case 2: c = ((*src & 0x30) >> 4) * 0x55;
  454. dest[1] = qRgb(c, c, c);
  455. case 1: c = ((*src & 0xc0) >> 6) * 0x55;
  456. dest[0] = qRgb(c, c, c);
  457. }
  458. }
  459. src += stride;
  460. }
  461. break;
  462. }
  463. case 4: {
  464. if (requiredSize > buffer.size())
  465. buffer.resize(requiredSize);
  466. // XXX: hw: replace by drawhelper functionality
  467. const int pixelsPerByte = 2;
  468. const int doAlign = r.x() & 1;
  469. const int doTail = (r.width() - doAlign) & 1;
  470. const int width8 = (r.width() - doAlign) / pixelsPerByte;
  471. uchar *b = reinterpret_cast<uchar*>(buffer.data());
  472. img = QImage(b, r.width(), r.height(), QImage::Format_RGB32);
  473. for (int y = 0; y < r.height(); ++y) {
  474. const quint8 *sptr = mView->data()
  475. + (r.y() + y) * mView->linestep()
  476. + r.x() / pixelsPerByte;
  477. quint32 *dptr = reinterpret_cast<quint32*>(img.scanLine(y));
  478. if (doAlign) {
  479. quint8 c = (*sptr++ & 0x0f);
  480. c |= (c << 4);
  481. *dptr++ = qRgb(c, c, c);
  482. }
  483. for (int i = 0; i < width8; ++i) {
  484. quint8 c1 = (*sptr >> 4);
  485. quint8 c2 = (*sptr & 0x0f);
  486. c1 |= (c1 << 4);
  487. c2 |= (c2 << 4);
  488. *dptr++ = qRgb(c1, c1, c1);
  489. *dptr++ = qRgb(c2, c2, c2);
  490. ++sptr;
  491. }
  492. if (doTail) {
  493. quint8 c = *sptr >> 4;
  494. c |= (c << 4);
  495. *dptr = qRgb(c, c, c);
  496. }
  497. }
  498. break;
  499. }
  500. case 12:
  501. img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2),
  502. r.width(), r.height(), mView->linestep(),
  503. QImage::Format_RGB444);
  504. break;
  505. case 15:
  506. img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2),
  507. r.width(), r.height(), mView->linestep(),
  508. QImage::Format_RGB555);
  509. break;
  510. case 16:
  511. img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2),
  512. r.width(), r.height(), mView->linestep(),
  513. QImage::Format_RGB16);
  514. break;
  515. case 18:
  516. img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 3),
  517. r.width(), r.height(), mView->linestep(),
  518. QImage::Format_RGB666);
  519. break;
  520. case 24:
  521. img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 3),
  522. r.width(), r.height(), mView->linestep(),
  523. QImage::Format_RGB888);
  524. break;
  525. case 32:
  526. img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 4),
  527. r.width(), r.height(), mView->linestep(),
  528. viewFormat == ARGBFormat ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
  529. break;
  530. case 8:
  531. img = QImage(mView->data() + r.y() * mView->linestep() + r.x(),
  532. r.width(), r.height(), mView->linestep(),
  533. QImage::Format_Indexed8);
  534. img.setColorTable(mView->clut());
  535. if (img.colorCount() <= 0)
  536. img = QImage();
  537. break;
  538. }
  539. if (rgb_swapped)
  540. img = img.rgbSwapped();
  541. if ( brightness != 255 ) {
  542. if (img.format() == QImage::Format_Indexed8) {
  543. QVector<QRgb> c = img.colorTable();
  544. dim(c.data(),c.count(),brightness);
  545. img.setColorTable(c);
  546. } else {
  547. if ( img.format() != QImage::Format_ARGB32_Premultiplied )
  548. img = img.convertToFormat(QImage::Format_RGB32);
  549. // NOTE: calling bits() may change byteCount(), so do not
  550. // pass them as parameters (which are evaluated right-to-left).
  551. QRgb *b = (QRgb*)img.bits();
  552. int n = img.byteCount()/4;
  553. dim(b,n,brightness);
  554. }
  555. }
  556. return img;
  557. }
  558. static int findMultiple(int start, double m, int limit, int step)
  559. {
  560. int r = start;
  561. while (r != limit) {
  562. if (int(int(r * m)/m) == r)
  563. break;
  564. r += step;
  565. }
  566. return r;
  567. }
  568. void QVFbView::drawScreen(const QRect &rect)
  569. {
  570. QRect r = QRect(0, 0, mView->width(), mView->height());
  571. if (hzm == 1.0 && vzm == 1.0) // hw: workaround for 4.3.1
  572. r &= rect;
  573. if (int(hzm) != hzm || int(vzm) != vzm) {
  574. r.setLeft(findMultiple(r.left(),hzm,0,-1));
  575. r.setTop(findMultiple(r.top(),vzm,0,-1));
  576. int w = findMultiple(r.width(),hzm,mView->width(),1);
  577. int h = findMultiple(r.height(),vzm,mView->height(),1);
  578. r.setRight(r.left()+w-1);
  579. r.setBottom(r.top()+h-1);
  580. }
  581. int leading;
  582. const QImage img = getBuffer(r, leading);
  583. QPixmap pm;
  584. if (hzm == 1.0 && vzm == 1.0) {
  585. pm = QPixmap::fromImage(img);
  586. } else if (emulateLcdScreen && hzm == 3.0 && vzm == 3.0) {
  587. QImage img2(img.width()*3, img.height(), QImage::Format_RGB32);
  588. for (int row = 0; row < img2.height(); row++) {
  589. QRgb *dptr = (QRgb*)img2.scanLine(row);
  590. QRgb *sptr = (QRgb*)img.scanLine(row);
  591. for (int col = 0; col < img.width(); col++) {
  592. QRgb s = *sptr++;
  593. *dptr++ = qRgb(qRed(s),0,0);
  594. *dptr++ = qRgb(0,qGreen(s),0);
  595. *dptr++ = qRgb(0,0,qBlue(s));
  596. }
  597. }
  598. QMatrix m;
  599. m.scale(1.0, 3.0);
  600. pm = QPixmap::fromImage(img2);
  601. pm = pm.transformed(m);
  602. } else if (int(hzm) == hzm && int(vzm) == vzm) {
  603. QMatrix m;
  604. m.scale(hzm,vzm);
  605. pm = QPixmap::fromImage(img);
  606. pm = pm.transformed(m);
  607. } else {
  608. pm = QPixmap::fromImage(img.scaled(int(img.width()*hzm),int(img.height()*vzm), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
  609. }
  610. int x1 = r.x();
  611. int y1 = r.y();
  612. int leadingX = leading;
  613. int leadingY = 0;
  614. // Do the rotation thing
  615. int rotX1 = mView->width() - x1 - img.width();
  616. int rotY1 = mView->height() - y1 - img.height();
  617. int rotLeadingX = (leading) ? mView->width() - leadingX - img.width() : 0;
  618. int rotLeadingY = 0;
  619. switch (rotation) {
  620. case Rot0:
  621. break;
  622. case Rot90:
  623. leadingY = leadingX;
  624. leadingX = rotLeadingY;
  625. y1 = x1;
  626. x1 = rotY1;
  627. break;
  628. case Rot180:
  629. leadingX = rotLeadingX;
  630. leadingY = leadingY;
  631. x1 = rotX1;
  632. y1 = rotY1;
  633. break;
  634. case Rot270:
  635. leadingX = leadingY;
  636. leadingY = rotLeadingX;
  637. x1 = y1;
  638. y1 = rotX1;
  639. break;
  640. default:
  641. break;
  642. }
  643. x1 = int(x1*hzm);
  644. y1 = int(y1*vzm);
  645. leadingX = int(leadingX*hzm);
  646. leadingY = int(leadingY*vzm);
  647. if (rotation != 0) {
  648. QMatrix m;
  649. m.rotate(rotation * 90.0);
  650. pm = pm.transformed(m);
  651. }
  652. QPainter p(this);
  653. if (viewFormat == ARGBFormat) {
  654. QPixmap bg(":/res/images/logo-nt.png");
  655. p.fillRect(x1,y1,pm.width(), pm.height(), QBrush(bg));
  656. }
  657. p.drawPixmap(x1, y1, pm, leadingX, leadingY, pm.width(), pm.height());
  658. }
  659. //bool QVFbView::eventFilter(QObject *obj, QEvent *e)
  660. //{
  661. // if (obj == this &&
  662. // (e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut))
  663. // return true;
  664. //
  665. // return QWidgetView::eventFilter(obj, e);
  666. //}
  667. void QVFbView::paintEvent(QPaintEvent *e)
  668. {
  669. drawScreen(mapToDevice(e->rect(),QSize(int(width()/hzm), int(height()/vzm)),rotation));
  670. }
  671. void QVFbView::mousePressEvent(QMouseEvent *e)
  672. {
  673. sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0);
  674. }
  675. void QVFbView::contextMenuEvent(QContextMenuEvent*)
  676. {
  677. }
  678. void QVFbView::mouseDoubleClickEvent(QMouseEvent *e)
  679. {
  680. sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0);
  681. }
  682. void QVFbView::mouseReleaseEvent(QMouseEvent *e)
  683. {
  684. sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0);
  685. }
  686. void QVFbView::skinMouseEvent(QMouseEvent *e)
  687. {
  688. sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0);
  689. }
  690. void QVFbView::mouseMoveEvent(QMouseEvent *e)
  691. {
  692. if (!emulateTouchscreen || (e->buttons() & Qt::MouseButtonMask))
  693. sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0);
  694. }
  695. void QVFbView::wheelEvent(QWheelEvent *e)
  696. {
  697. if (!e)
  698. return;
  699. sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), e->delta());
  700. }
  701. void QVFbView::setTouchscreenEmulation(bool b)
  702. {
  703. emulateTouchscreen = b;
  704. }
  705. void QVFbView::setLcdScreenEmulation(bool b)
  706. {
  707. emulateLcdScreen = b;
  708. }
  709. void QVFbView::setViewFormat(PixelFormat f)
  710. {
  711. if (viewFormat == f)
  712. return;
  713. viewFormat = f;
  714. setAttribute(Qt::WA_PaintOnScreen, viewFormat != ARGBFormat);
  715. }
  716. #ifdef Q_WS_X11
  717. void QVFbView::embedDisplay(WId windowId)
  718. {
  719. if (windowId == 0) {
  720. delete embedContainer;
  721. embedContainer = 0;
  722. return;
  723. }
  724. if (!embedContainer) {
  725. embedContainer = new QX11EmbedContainer(this);
  726. embedContainer->setGeometry(rect());
  727. embedContainer->show();
  728. }
  729. embedContainer->embedClient(windowId);
  730. }
  731. #endif
  732. bool QVFbView::event(QEvent *e)
  733. {
  734. if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) {
  735. QKeyEvent *ke = static_cast<QKeyEvent*>(e);
  736. sendKeyboardData(ke->text(), ke->key(),
  737. ke->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier),
  738. ke->type() == QEvent::KeyPress, ke->isAutoRepeat());
  739. ke->accept();
  740. return true;
  741. }
  742. return QVFbAbstractView::event(e);
  743. }
  744. void QVFbView::keyPressEvent(QKeyEvent *e)
  745. {
  746. sendKeyboardData(e->text(), e->key(),
  747. e->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier),
  748. true, e->isAutoRepeat());
  749. }
  750. void QVFbView::keyReleaseEvent(QKeyEvent *e)
  751. {
  752. sendKeyboardData(e->text(), e->key(),
  753. e->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier),
  754. false, e->isAutoRepeat());
  755. }
  756. QImage QVFbView::image() const
  757. {
  758. int l;
  759. QImage r = getBuffer(QRect(0, 0, mView->width(), mView->height()), l).copy();
  760. return r;
  761. }
  762. void QVFbView::startAnimation(const QString& filename)
  763. {
  764. delete animation;
  765. animation = new QAnimationWriter(filename,"MNG");
  766. animation->setFrameRate(refreshRate);
  767. animation->appendFrame(QImage(mView->data(),
  768. mView->width(), mView->height(), QImage::Format_RGB32));
  769. }
  770. void QVFbView::stopAnimation()
  771. {
  772. delete animation;
  773. animation = 0;
  774. }
  775. void QVFbView::skinKeyPressEvent(int code, const QString& text, bool autorep)
  776. {
  777. QKeyEvent e(QEvent::KeyPress,code,0,text,autorep);
  778. keyPressEvent(&e);
  779. }
  780. void QVFbView::skinKeyReleaseEvent(int code, const QString& text, bool autorep)
  781. {
  782. QKeyEvent e(QEvent::KeyRelease,code,0,text,autorep);
  783. keyReleaseEvent(&e);
  784. }
  785. QT_END_NAMESPACE