📄 qvfbview.cpp
字号:
/******************************************************************************** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).** Contact: Qt Software Information (qt-info@nokia.com)**** This file is part of the tools applications of the Qt Toolkit.**** $QT_BEGIN_LICENSE:LGPL$** Commercial Usage** Licensees holding valid Qt Commercial licenses may use this file in** accordance with the Qt Commercial License Agreement provided with the** Software or, alternatively, in accordance with the terms contained in** a written agreement between you and Nokia.**** GNU Lesser General Public License Usage** Alternatively, this file may be used under the terms of the GNU Lesser** General Public License version 2.1 as published by the Free Software** Foundation and appearing in the file LICENSE.LGPL included in the** packaging of this file. Please review the following information to** ensure the GNU Lesser General Public License version 2.1 requirements** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.**** In addition, as a special exception, Nokia gives you certain** additional rights. These rights are described in the Nokia Qt LGPL** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this** package.**** GNU General Public License Usage** Alternatively, this file may be used under the terms of the GNU** General Public License version 3.0 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file. Please review the following information to** ensure the GNU General Public License version 3.0 requirements will be** met: http://www.gnu.org/copyleft/gpl.html.**** If you are unsure which license is appropriate for your use, please** contact the sales department at qt-sales@nokia.com.** $QT_END_LICENSE$******************************************************************************/#include "qvfbview.h"#include "qvfbshmem.h"#include "qvfbmmap.h"#include "qanimationwriter.h"#include <QApplication>#include <QPainter>#include <QImage>#include <QBitmap>#include <QMatrix>#include <QPaintEvent>#include <QScrollArea>#include <QFile>#include <QDebug>#ifdef Q_WS_X11#include <QX11EmbedContainer>#include <QHBoxLayout>#endif#include <stdlib.h>#include <unistd.h>#include <sys/ipc.h>#include <sys/types.h>#include <sys/shm.h>#include <sys/stat.h>#include <sys/sem.h>#include <fcntl.h>#include <errno.h>#include <math.h>QT_BEGIN_NAMESPACEextern int qvfb_protocol;QVFbAbstractView::QVFbAbstractView( QWidget *parent )#ifdef QVFB_USE_GLWIDGET : QGLWidget( parent )#else : QWidget( parent )#endif{}QVFbAbstractView::~QVFbAbstractView(){}QVFbView::QVFbView(int id, int w, int h, int d, Rotation r, QWidget *parent) : QVFbAbstractView(parent), viewdepth(d), viewFormat(DefaultFormat), rsh(0), gsh(0), bsh(0), rmax(15), gmax(15), bmax(15), contentsWidth(w), contentsHeight(h), gred(1.0), ggreen(1.0), gblue(1.0), gammatable(0), refreshRate(30), animation(0), hzm(0.0), vzm(0.0), mView(0), emulateTouchscreen(false), emulateLcdScreen(false), rotation(r)#ifdef Q_WS_X11 , embedContainer(0)#endif{ switch(qvfb_protocol) { default: case 0: mView = new QShMemViewProtocol(id, QSize(w, h), d, this); break; case 1: mView = new QMMapViewProtocol(id, QSize(w, h), d, this); break; } connect(mView, SIGNAL(displayDataChanged(const QRect &)), SLOT(refreshDisplay(const QRect &)));#ifdef Q_WS_X11 connect(mView, SIGNAL(displayEmbedRequested(WId)), this, SLOT(embedDisplay(WId)));#endif setAttribute(Qt::WA_PaintOnScreen, viewFormat != ARGBFormat); setMouseTracking(true); setFocusPolicy(Qt::StrongFocus); setAttribute(Qt::WA_NoSystemBackground); setZoom(1.0,1.0); setGamma(1.0,1.0,1.0); mView->setRate(30);}QVFbView::~QVFbView(){ stopAnimation(); sendKeyboardData(0, 0, 0, true, false); // magic die key#ifdef Q_WS_X11 delete embedContainer;#endif}QSize QVFbView::sizeHint() const{ return QSize(contentsWidth, contentsHeight);}void QVFbView::setRate(int i){ mView->setRate(i);}void QVFbView::setGamma(double gr, double gg, double gb){ gred = gr; ggreen = gg; gblue = gb; switch (viewdepth) { case 12: rsh = 12; gsh = 7; bsh = 1; rmax = 15; gmax = 15; bmax = 15; break; case 15: rsh = 10; gsh = 5; bsh = 0; rmax = 31; gmax = 31; bmax = 31; break; case 16: rsh = 11; gsh = 5; bsh = 0; rmax = 31; gmax = 63; bmax = 31; break; case 18: rsh = 12; gsh = 6; bsh = 0; rmax = 63; gmax = 63; bmax = 63; break; case 24: case 32: rsh = 16; gsh = 8; bsh = 0; rmax = 255; gmax = 255; bmax = 255; } int mm = qMax(rmax,qMax(gmax,bmax))+1; if (gammatable) delete [] gammatable; gammatable = new QRgb[mm]; for (int i=0; i<mm; i++) { int r = int(pow(i,gr)*255/rmax); int g = int(pow(i,gg)*255/gmax); int b = int(pow(i,gb)*255/bmax); if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; gammatable[i] = qRgb(r,g,b);//qDebug("%d: %d,%d,%d",i,r,g,b); } mView->flushChanges();}void QVFbView::getGamma(int i, QRgb& rgb){ if (i > 255) i = 255; if (i < 0) i = 0; rgb = qRgb(qRed(gammatable[i*rmax/255]), qGreen(gammatable[i*rmax/255]), qBlue(gammatable[i*rmax/255]));}int QVFbView::displayId() const{ return mView->id();}int QVFbView::displayWidth() const{ return mView->width();}int QVFbView::displayHeight() const{ return mView->height();}int QVFbView::displayDepth() const{ return viewdepth;}QVFbView::PixelFormat QVFbView::displayFormat() const{ return viewFormat;}QVFbView::Rotation QVFbView::displayRotation() const{ return rotation;}void QVFbView::setZoom(double hz, double vz){ if (hzm != hz || vzm != vz) { hzm = hz; vzm = vz; mView->flushChanges(); contentsWidth = int(displayWidth()*hz); contentsHeight = int(displayHeight()*vz); if (rotation & 1) qSwap(contentsWidth,contentsHeight); resize(contentsWidth, contentsHeight); if (isVisible()) { updateGeometry(); qApp->sendPostedEvents(); topLevelWidget()->adjustSize(); update(); } }}void QVFbView::setRotation(QVFbView::Rotation r){ rotation = r; // Force update... double ohzm = hzm; hzm=0.0; setZoom(ohzm,vzm);}static QRect mapToDevice(const QRect &r, const QSize &s, QVFbView::Rotation rotation){ int x1 = r.x(); int y1 = r.y(); int x2 = r.right(); int y2 = r.bottom(); int w = s.width(); int h = s.height(); switch (rotation) { case QVFbView::Rot90: return QRect( QPoint(y1, w - x1), QPoint(y2, w - x2)).normalized(); case QVFbView::Rot180: return QRect( QPoint(w - x1, h - y1), QPoint(w - x2, h - y2)).normalized(); case QVFbView::Rot270: return QRect( QPoint(h - y1, x1), QPoint(h - y2, x2)).normalized(); default: break; } return r;}static QRect mapFromDevice(const QRect &r, const QSize &s, QVFbView::Rotation rotation){ return mapToDevice(r,s,QVFbView::Rotation(4-(int)rotation));}void QVFbView::sendMouseData(const QPoint &pos, int buttons, int wheel){ QPoint p = mapToDevice(QRect(pos,QSize(1,1)), QSize(int(width()/hzm), int(height()/vzm)), rotation).topLeft(); mView->sendMouseData(p, buttons, wheel);}void QVFbView::sendKeyboardData(QString unicode, int keycode, int modifiers, bool press, bool repeat){ mView->sendKeyboardData(unicode, keycode, modifiers, press, repeat);}void QVFbView::refreshDisplay(const QRect &r){ if (animation) { if (r.isEmpty()) { animation->appendBlankFrame(); } else { int l; QImage img = getBuffer(r, l); animation->appendFrame(img,QPoint(r.x(),r.y())); } } if (!r.isNull()) { if (hzm == 1.0 && vzm == 1.0) // hw: workaround for 4.3.1 update(mapFromDevice(r, QSize(displayWidth(), displayHeight()), rotation)); else update(); }}static void dim(QRgb* rgb, int n, int brightness){ uchar* b = (uchar*)rgb;#if Q_BYTE_ORDER == Q_BIG_ENDIAN b++;#endif while (n--) { b[0] = (uint)b[0] * brightness / 255; b[1] = (uint)b[1] * brightness / 255; b[2] = (uint)b[2] * brightness / 255; b += 4; }}QImage QVFbView::getBuffer(const QRect &r, int &leading) const{ const int brightness = mView->brightness(); if ( brightness == 0 ) { QImage img(r.size(),QImage::Format_RGB32); img.fill(0); leading = 0; return img; } static QByteArray buffer; const int requiredSize = r.width() * r.height() * 4; QImage img; leading = 0; switch (viewdepth) { case 1: { if (requiredSize > buffer.size()) buffer.resize(requiredSize); // XXX: hw: replace by drawhelper functionality const int pixelsPerByte = 8; quint8 *src = reinterpret_cast<quint8*>(mView->data()) + r.y() * mView->linestep() + r.x() / pixelsPerByte; const int align = qMin(r.width(), (8 - (r.x() & 7)) & 7); const int doAlign = (align > 0 ? 1 : 0); const int tail = qMin(r.width(), (r.width() - align) & 7); const int doTail = (tail > 0 ? 1 : 0); const int width8 = (r.width() - align) / pixelsPerByte; const int stride = mView->linestep() - (width8 + doAlign); uchar *b = reinterpret_cast<uchar*>(buffer.data()); img = QImage(b, r.width(), r.height(), QImage::Format_RGB32); for (int y = 0; y < r.height(); ++y) { quint32 *dest = reinterpret_cast<quint32*>(img.scanLine(y)); quint8 c; if (doAlign) { switch (align) { case 7: c = ((*src & 0x40) >> 6) * 0xff; *dest++ = qRgb(c, c, c); case 6: c = ((*src & 0x20) >> 5) * 0xff; *dest++ = qRgb(c, c, c); case 5: c = ((*src & 0x10) >> 4) * 0xff; *dest++ = qRgb(c, c, c); case 4: c = ((*src & 0x08) >> 3) * 0xff; *dest++ = qRgb(c, c, c); case 3: c = ((*src & 0x04) >> 2) * 0xff; *dest++ = qRgb(c, c, c); case 2: c = ((*src & 0x02) >> 1) * 0xff; *dest++ = qRgb(c, c, c); case 1: c = ((*src & 0x01)) * 0xff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -