下载地址
官方下载地址:
http://download.qt.io/archive/qt/5.9/5.9.8/single/
国内使用清华tuna的镜像速度会更快:
https://mirrors.tuna.tsinghua.edu.cn/qt/archive/qt/5.9/5.9.8/single/
编译环境
Ubuntu 18.04.3 LTS
准备工作
- 交叉编译安装tslib;
- 交叉编译安装libiconv;
- 安装QT相关库:
sudo apt-get install qtdeclarative5-dev sudo apt-get install qtdeclarative5-dev-tools
- 下载qt源码,并解压;
- 下载旋转显示的补丁包,对qtbase/src/plugins/platforms/linuxfb目录下qlinuxfbscreen.h、qlinuxfbscreen.cpp2个文件进行修改。暂时不清除csdn怎么上传附件,直接贴源码如下:
qlinuxfbscreen.h:
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QLINUXFBSCREEN_H
#define QLINUXFBSCREEN_H
#include <QtFbSupport/private/qfbscreen_p.h>
QT_BEGIN_NAMESPACE
class QPainter;
class QFbCursor;
class QLinuxFbScreen : public QFbScreen
{
Q_OBJECT
public:
QLinuxFbScreen(const QStringList &args);
~QLinuxFbScreen();
bool initialize() override;
QPixmap grabWindow(WId wid, int x, int y, int width, int height) const override;
QRegion doRedraw() override;
private:
QStringList mArgs;
int mFbFd;
int mTtyFd;
int mRotation;
QImage mFbScreenImage;
int mBytesPerLine;
int mOldTtyMode;
struct {
uchar *data;
int offset, size;
} mMmap;
QPainter *mBlitter;
};
QT_END_NAMESPACE
#endif // QLINUXFBSCREEN_H
qlinuxfbscreen.cpp
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qlinuxfbscreen.h"
#include <QtFbSupport/private/qfbcursor_p.h>
#include <QtFbSupport/private/qfbwindow_p.h>
#include <QtCore/QFile>
#include <QtCore/QRegularExpression>
#include <QtGui/QPainter>
#include <private/qcore_unix_p.h> // overrides QT_OPEN
#include <qimage.h>
#include <qdebug.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <linux/kd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <limits.h>
#include <signal.h>
#include <linux/fb.h>
QT_BEGIN_NAMESPACE
static int openFramebufferDevice(const QString &dev)
{
int fd = -1;
if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)
fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);
if (fd == -1) {
if (access(dev.toLatin1().constData(), R_OK) == 0)
fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);
}
return fd;
}
static int determineDepth(const fb_var_screeninfo &vinfo)
{
int depth = vinfo.bits_per_pixel;
if (depth== 24) {
depth = vinfo.red.length + vinfo.green.length + vinfo.blue.length;
if (depth <= 0)
depth = 24; // reset if color component lengths are not reported
} else if (depth == 16) {
depth = vinfo.red.length + vinfo.green.length + vinfo.blue.length;
if (depth <= 0)
depth = 16;
}
return depth;
}
static QRect determineGeometry(const fb_var_screeninfo &vinfo, const QRect &userGeometry)
{
int xoff = vinfo.xoffset;
int yoff = vinfo.yoffset;
int w, h;
if (userGeometry.isValid()) {
w = userGeometry.width();
h = userGeometry.height();
if ((uint)w > vinfo.xres)
w = vinfo.xres;
if ((uint)h > vinfo.yres)
h = vinfo.yres;
int xxoff = userGeometry.x(), yyoff = userGeometry.y();
if (xxoff != 0 || yyoff != 0) {
if (xxoff < 0 || xxoff + w > (int)(vinfo.xres))
xxoff = vinfo.xres - w;
if (yyoff < 0 || yyoff + h > (int)(vinfo.yres))
yyoff = vinfo.yres - h;
xoff += xxoff;
yoff += yyoff;
} else {
xoff += (vinfo.xres - w)/2;
yoff += (vinfo.yres - h)/2;
}
} else {
w = vinfo.xres;
h = vinfo.yres;
}
if (w == 0 || h == 0) {
qWarning("Unable to find screen geometry, using 320x240");
w = 320;
h = 240;
}
return QRect(xoff, yoff, w, h);
}
static QSizeF determinePhysicalSize(const fb_var_screeninfo &vinfo, const QSize &mmSize, const QSize &res)
{
int mmWidth = mmSize.width(), mmHeight = mmSize.height();
if (mmWidth <= 0 && mmHeight <= 0) {
if (vinfo.width != 0 && vinfo.height != 0
&& vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {
mmWidth = vinfo.width;
mmHeight = vinfo.height;
} else {
const int dpi = 100;
mmWidth = qRound(res.width() * 25.4 / dpi);
mmHeight = qRound(res.height() * 25.4 / dpi);
}
} else if (mmWidth > 0 && mmHeight <= 0) {
mmHeight = res.height() * mmWidth/res.width();
} else if (mmHeight > 0 && mmWidth <= 0) {
mmWidth = res.width() * mmHeight/res.height();
}
return QSize(mmWidth, mmHeight);
}
static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
{
const fb_bitfield rgba[4] = { info.red, info.green,
info.blue, info.transp };
QImage::Format format = QImage::Format_Invalid;
switch (depth) {
case 32: {
const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0},
{0, 8, 0}, {24, 8, 0}};
const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0},
{16, 8, 0}, {24, 8, 0}};
if (memcmp(rgba, argb8888, 4 * sizeof(fb_bitfield)) == 0) {
format = QImage::Format_ARGB32;
} else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) {
format = QImage::Format_RGB32;
} else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) {
format = QImage::Format_RGB32;
// pixeltype = BGRPixel;
}
break;
}
case 24: {
const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0},
{0, 8, 0}, {0, 0, 0}};
const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0},
{16, 8, 0}, {0, 0, 0}};
if (memcmp(rgba, rgb888, 3 * sizeof(fb_bitfield)) == 0) {
format = QImage::Format_RGB888;
} else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) {
format = QImage::Format_RGB888;
// pixeltype = BGRPixel;
}
break;
}
case 18: {
const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0},
{0, 6, 0}, {0, 0, 0}};
if (memcmp(rgba, rgb666, 3 * sizeof(fb_bitfield)) == 0)
format = QImage::Format_RGB666;
break;
}
case 16: {
const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0},
{0, 5, 0}, {0, 0, 0}};
const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0},
{11, 5, 0}, {0, 0, 0}};
if (memcmp(rgba, rgb565, 3 * sizeof(fb_bitfield)) == 0) {
format = QImage::Format_RGB16;
} else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) {
format = QImage::Format_RGB16;
// pixeltype = BGRPixel;
}
break;
}
case 15: {
const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0},
{0, 5, 0}, {15, 1, 0}};
const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0},
{10, 5, 0}, {15, 1, 0}};
if (memcmp(rgba, rgb1555, 3 * sizeof(fb_bitfield)) == 0) {
format = QImage::Format_RGB555;
} else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) {
format = QImage::Format_RGB555;
// pixeltype = BGRPixel;
}
break;
}
case 12: {
const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0},
{0, 4, 0}, {0, 0, 0}};
if (memcmp(rgba, rgb444, 3 * sizeof(fb_bitfield)) == 0)
format = QImage::Format_RGB444;
break;
}
case 8:
break;
case 1:
format = QImage::Format_Mono; //###: LSB???
break;
default:
break;
}
return format;
}
static int openTtyDevice(const QString &device)
{
const char *const devs[] = { "/dev/tty0", "/dev/tty", "/dev/console", 0 };
int fd = -1;
if (device.isEmpty()) {
for (const char * const *dev = devs; *dev; ++dev) {
fd = QT_OPEN(*dev, O_RDWR);
if (fd != -1)
break;
}
} else {
fd = QT_OPEN(QFile::encodeName(device).constData(), O_RDWR);
}
return fd;
}
static void switchToGraphicsMode(int ttyfd, bool doSwitch, int *oldMode)
{
// Do not warn if the switch fails: the ioctl fails when launching from a
// remote console and there is nothing we can do about it. The matching
// call in resetTty should at least fail then, too, so we do no harm.
if (ioctl(ttyfd, KDGETMODE, oldMode) == 0) {
if (doSwitch && *oldMode != KD_GRAPHICS)
ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);
}
}
static void resetTty(int ttyfd, int oldMode)
{
ioctl(ttyfd, KDSETMODE, oldMode);
QT_CLOSE(ttyfd);
}
static void blankScreen(int fd, bool on)
{
ioctl(fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING);
}
QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)
: 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+)"));
QRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"));
QString fbDevice, ttyDevice;
QSize userMmSize;
QRect userGeometry;
bool doSwitchToGraphicsMode = true;
// Parse arguments
for (const QString &arg : qAsConst(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);
else if (arg.contains(rotationRx, &match))
mRotation = match.captured(1).toInt();
}
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);
QRect originalGeometry = geometry;
if( mRotation == 90 || mRotation == 270 )
{
int tmp = geometry.width();
geometry.setWidth(geometry.height());
geometry.setHeight(tmp);
}
mGeometry = QRect(QPoint(0, 0), geometry.size());
mFormat = determineFormat(vinfo, mDepth);
mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, originalGeometry.size());
// 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;
}
mMmap.offset = originalGeometry.y() * mBytesPerLine + originalGeometry.x() * mDepth / 8;
mMmap.data = data + mMmap.offset;
QFbScreen::initializeCompositor();
mFbScreenImage = QImage(mMmap.data, originalGeometry.width(), originalGeometry.height(), mBytesPerLine, mFormat);
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);
mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
//for (const QRect &rect : touched)
// mBlitter->drawImage(rect, mScreenImage, rect);
QVector<QRect> rects = touched.rects();
for (int i = 0; i < rects.size(); i++)
{
if( mRotation == 90 || mRotation == 270 )
{
mBlitter->translate(mGeometry.height()/2, mGeometry.width()/2);
}
else if( mRotation == 180 )
{
mBlitter->translate(mGeometry.width()/2, mGeometry.height()/2);
}
if( mRotation != 0 )
{
mBlitter->rotate(mRotation);
mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);
}
mBlitter->drawImage(rects[i], mScreenImage, rects[i]);
mBlitter->resetTransform();
}
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();
}
QT_END_NAMESPACE
编译配置
假设:
- 交叉编译工具:arm-linux-
使用的交叉编译工具版本信息如下:Target: arm-linux-gnueabi Configured with: --target=arm-linux-gnueabi --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --with-gnu-as --with-gnu-ld --enable-languages=c,c++ --enable-shared --enable-lto --enable-symvers=gnu --enable-__cxa_atexit --disable-nls --enable-clocale=gnu --enable-libgomp --disable-libitm --enable-poison-system-directories Thread model: posix gcc version 6.3.0
- 交叉编译结果安装目录:/home/user/cross-compile/
配置及编译:
-
在qt-everywhere-opensource-src-5.9.8/qtbase/mkspecs/目录下,创建以交叉编译工具命名的文件夹,例如arm-linux-g++;
-
可以拷贝linux-arm-gnueabi-g++目录下的文件过去作为参考,然后修改arm-linux-g++/qmake.conf文件:
# # qmake configuration for building with arm-linux-gnueabi-g++ # MAKEFILE_GENERATOR = UNIX CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib ###### QT_QPA_DEFAULT_PLATFORM = linuxfb QMAKE_CFLAGS += -O2 -march=armv7-a QMAKE_CFLAGS_RELEASE += -O2 -march=armv7-a QMAKE_CXXFLAGS += -O2 -march=armv7-a QMAKE_CXXFLAGS_RELEASE += -O2 -march=armv7-a ###### include(../common/linux.conf) include(../common/gcc-base-unix.conf) include(../common/g++-unix.conf) # modifications to g++.conf QMAKE_CC = arm-linux-gcc QMAKE_CXX = arm-linux-g++ QMAKE_LINK = arm-linux-g++ QMAKE_LINK_SHLIB = arm-linux-g++ # modifications to linux.conf QMAKE_AR = arm-linux-ar cqs QMAKE_OBJCOPY = arm-linux-objcopy QMAKE_NM = arm-linux-nm -P QMAKE_STRIP = arm-linux-strip load(qt_config)
-
configure配置如下:
./configure -prefix /home/user/cross-compile/qt5 -recheck-all -opensource -confirm-license -optimized-qmake -release -no-separate-debug-info -strip -shared -static -xplatform arm-linux-g++ -c++std c++1z -no-sse2 -pch -compile-examples -gui -widgets -no-dbus -no-openssl -no-cups -no-opengl -linuxfb -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype -xinput2 -evdev -tslib -L/home/user/cross-compile/tslib/lib -I/home/user/cross-compile/tslib/include
- -prefix:指定交叉编译后的安装目录;
- -recheck-all:丢弃缓存的之前配置的检测信息,如果进行多次configure建议加上该选项;
- -opensource -confirm-license:使用开源版本,并接受license;
- -release:发布版,关闭debug;
- -strip:压缩so文件。吐槽一下,qt实在太大了,如果UI界面不复杂,建议用linuxfb+tslib+freetype2,自己实现;
- -shared:生成动态库;
- -static:生成静态库;
- -xplatform arm-linux-g++:交叉编译,使用arm-linux-g++进行编译;
- -c++std c++1z:使用c++1z标准;
- -no-sse2:不使用sse2指令集;
- -pch:使用预编译的头;
- -compile-examples:编译示例;
- -gui:编译gui模块及相关依赖;
- -widgets:编译widgets模块及相关依赖;
- -no-dbus -no-openssl -no-cups -no-opengl:不编译相关模块。dbus在wifi、蓝牙模块中常用,这里不需要;
- -linuxfb:使用linuxfb显示;
- -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype:使用qt内置的相关功能模块;
- -xinput2:使能xinput2;
- -evdev:支持evdev;
- -tslib -L/home/user/cross-compile/tslib/lib -I/home/user/cross-compile/tslib/include:使用tslib作为触摸输入,并指定交叉编译后的tslib的库和头文件目录;
- 编译及安装:
make -j7
j后面的参数根据编译主机CPU的线程数目而定,建议线程数目减一。例如4核8线程的CPU,-j7就OK。笔记本4核8线程的CPU,以-j7为参数,大约要编译半小时以上。
编译完成后,执行安装即可:
make install
使用配置
- 将交叉编译的libiconv库,拷贝到目标板;
- 按说明,将交叉编译的tslib拷贝到目标板;
- 将编译生成的qt/lib目录下的文件及文件夹拷贝到usr/local/lib/qt5目录下;
- 将待使用的中文字库,拷贝到usr/local/lib/qt5/fonts目录下;
修改环境变量参数如下(tslib的环境变量参数,请参考tslib):
export QTDIR=/usr/local/lib/qt5
export QT_QPA_FONTDIR=$QTDIR/lib/fonts
export QT_QPA_PLATFORM_PLUGIN_PATH=$QTDIR/plugins/
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:size=480x800:offset=0x0:rotation=0
export QT_QPA_FB_TSLIB=1
export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/event0
export LD_PRELOAD=/usr/local/lib/preloadable_libiconv.so