Chinaunix首页 | 论坛 | 博客
  • 博客访问: 30101944
  • 博文数量: 230
  • 博客积分: 2868
  • 博客等级: 少校
  • 技术积分: 2223
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-08 21:48
个人简介

Live & Learn

文章分类

全部博文(230)

文章存档

2022年(2)

2019年(5)

2018年(15)

2017年(42)

2016年(24)

2015年(13)

2014年(1)

2012年(5)

2011年(58)

2010年(56)

2009年(9)

我的朋友

分类: LINUX

2019-04-15 22:15:16

1,修改Qt5源码:


(1) 修改linuxfb/qlinuxfbscreen.h,如下所示:


class QLinuxFbScreen : public QFbScreen
{
    Q_OBJECT
public:
    QLinuxFbScreen(const QStringList &args);
    ~QLinuxFbScreen();
 
    bool initialize();
 
    QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
 
    QRegion doRedraw() Q_DECL_OVERRIDE;
 
private:
    QStringList mArgs;
    int mFbFd;
    int mTtyFd;

// add by immortal start
int mRotation;
// add by immortal end

    QImage mFbScreenImage;
    int mBytesPerLine;
    int mOldTtyMode;
 
    struct {
        uchar *data;
        int offset, size;
    } mMmap;
 
    QPainter *mBlitter;
};


(2) 修改linuxfb/qlinuxfbscreen.cpp,如下所示:


QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)
 //   : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0)  // modify by immortal
 : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0),mRotation(0)
{
    mMmap.data = 0;
}
 
QLinuxFbScreen::~QLinuxFbScreen()
{
    if (mFbFd != -1) {
        if (mMmap.data)
            munmap(mMmap.data - mMmap.offset, mMmap.size);
        close(mFbFd);
    }
 
    if (mTtyFd != -1)
        resetTty(mTtyFd, mOldTtyMode);
 
    delete mBlitter;
}
 
bool QLinuxFbScreen::initialize()
{
    QRegularExpression ttyRx(QLatin1String("tty=(.*)"));
    QRegularExpression fbRx(QLatin1String("fb=(.*)"));
    QRegularExpression mmSizeRx(QLatin1String("mmsize=(\\d+)x(\\d+)"));
    QRegularExpression sizeRx(QLatin1String("size=(\\d+)x(\\d+)"));
    QRegularExpression offsetRx(QLatin1String("offset=(\\d+)x(\\d+)"));

// add by immorta start
QRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"))
// add by immorta end
 
    QString fbDevice, ttyDevice;
    QSize userMmSize;
    QRect userGeometry;
    bool doSwitchToGraphicsMode = true;
 
    // Parse arguments
    foreach (const QString &arg, mArgs) {
        QRegularExpressionMatch match;
        if (arg == QLatin1String("nographicsmodeswitch"))
            doSwitchToGraphicsMode = false;
        else if (arg.contains(mmSizeRx, &match))
            userMmSize = QSize(match.captured(1).toInt(), match.captured(2).toInt());
        else if (arg.contains(sizeRx, &match))
            userGeometry.setSize(QSize(match.captured(1).toInt(), match.captured(2).toInt()));
        else if (arg.contains(offsetRx, &match))
            userGeometry.setTopLeft(QPoint(match.captured(1).toInt(), match.captured(2).toInt()));
        else if (arg.contains(ttyRx, &match))
            ttyDevice = match.captured(1);
        else if (arg.contains(fbRx, &match))
            fbDevice = match.captured(1);
// add by immortal start
else if (arg.contains(rotationRx, &match))
mRotation = match.captured(1).toInt();
// add by immortal end
    }
 
    if (fbDevice.isEmpty()) {
        fbDevice = QLatin1String("/dev/fb0");
        if (!QFile::exists(fbDevice))
            fbDevice = QLatin1String("/dev/graphics/fb0");
        if (!QFile::exists(fbDevice)) {
            qWarning("Unable to figure out framebuffer device. Specify it manually.");
            return false;
        }
    }
 
    // Open the device
    mFbFd = openFramebufferDevice(fbDevice);
    if (mFbFd == -1) {
        qErrnoWarning(errno, "Failed to open framebuffer %s", qPrintable(fbDevice));
        return false;
    }
 
    // Read the fixed and variable screen information
    fb_fix_screeninfo finfo;
    fb_var_screeninfo vinfo;
    memset(&vinfo, 0, sizeof(vinfo));
    memset(&finfo, 0, sizeof(finfo));
 
    if (ioctl(mFbFd, FBIOGET_FSCREENINFO, &finfo) != 0) {
        qErrnoWarning(errno, "Error reading fixed information");
        return false;
    }
 
    if (ioctl(mFbFd, FBIOGET_VSCREENINFO, &vinfo)) {
        qErrnoWarning(errno, "Error reading variable information");
        return false;
    }
 
    mDepth = determineDepth(vinfo);
    mBytesPerLine = finfo.line_length;
    QRect geometry = determineGeometry(vinfo, userGeometry);
// add by immortal start
QRect originalGeometry = geometry;
if( 90 == mRotation  || 270 == mRotation )
    {
int tmp = geometry.width();
        geometry.setWidth(geometry.height());
        geometry.setHeight(tmp);
    }
// add by immortal end
    mGeometry = QRect(QPoint(0, 0), geometry.size());
    mFormat = determineFormat(vinfo, mDepth);

// modify by immortal start
//   mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, originalGeometry.size());
// modify by immortal end

    // mmap the framebuffer
    mMmap.size = finfo.smem_len;
    uchar *data = (unsigned char *)mmap(0, mMmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, mFbFd, 0);
    if ((long)data == -1) {
        qErrnoWarning(errno, "Failed to mmap framebuffer");
        return false;
    }
// modify by immortal start
//   mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;
mMmap.offset = originalGeometry.y() * mBytesPerLine + originalGeometry.x() * mDepth / 8;
// modify by immortal end

    mMmap.data = data + mMmap.offset;
 
    QFbScreen::initializeCompositor();

    // modify by immortal start
// mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);
mFbScreenImage = QImage(mMmap.data, originalGeometry.width(), originalGeometry.height(), mBytesPerLine, mFormat);
// modify by immortal end

    mCursor = new QFbCursor(this);
 
    mTtyFd = openTtyDevice(ttyDevice);
    if (mTtyFd == -1)
        qErrnoWarning(errno, "Failed to open tty");
 
    switchToGraphicsMode(mTtyFd, doSwitchToGraphicsMode, &mOldTtyMode);
    blankScreen(mFbFd, false);
 
    return true;
}
 
QRegion QLinuxFbScreen::doRedraw()
{
    QRegion touched = QFbScreen::doRedraw();
 
    if (touched.isEmpty())
        return touched;
 
    if (!mBlitter)
        mBlitter = new QPainter(&mFbScreenImage);
 
    const QVector rects = touched.rects();
    mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
 
for (int i = 0; i < rects.size(); ++i)
// add by immortal start
{
if( 90 == mRotation || 270 == mRotation )
        {
mBlitter->translate(mGeometry.height()/2, mGeometry.width()/2);
        }
        else if( 180 == mRotation )
        {
            mBlitter->translate(mGeometry.width()/2, mGeometry.height()/2);
        }
        if( mRotation != 0 )
        {
            mBlitter->rotate(mRotation);
            mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);
        }
// add by immortal end

        mBlitter->drawImage(rects[i], *mScreenImage, rects[i]);

// add by immortal start
mBlitter->resetTransform();
// add by immortal end
    }
    return touched;
}
 
// grabWindow() grabs "from the screen" not from the backingstores.
// In linuxfb's case it will also include the mouse cursor.
QPixmap QLinuxFbScreen::grabWindow(WId wid, int x, int y, int width, int height) const
{
    if (!wid) {
        if (width < 0)
            width = mFbScreenImage.width() - x;
        if (height < 0)
            height = mFbScreenImage.height() - y;
        return QPixmap::fromImage(mFbScreenImage).copy(x, y, width, height);
    }
    QFbWindow *window = windowForId(wid);
    if (window) {
        const QRect geom = window->geometry();
        if (width < 0)
            width = geom.width() - x;
        if (height < 0)
            height = geom.height() - y;
        QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));
        rect &= window->geometry();
        return QPixmap::fromImage(mFbScreenImage).copy(rect);
    }
    return QPixmap();
}
2,配置环境变量:


export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:rotation=90 
或者运行程序时加入参数: ./app -platform linuxfb:fb=/dev/fb0:rotatio=90
3,重新编译 Qt5.X 源码,替换之前生成的 LinuxFB 的库文件,屏幕即可像Qt4那般进行旋转(PS:网上旋转的方法大多是利用动画框架QGraphicsView的视图场景进行旋转的,这样做的弊端在于:首先,子界面控件会接收不到任何的触摸事件,不知道是什么鬼;其次,CPU利用率会很高,功耗大大增加)


阅读(8399) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~