zoukankan      html  css  js  c++  java
  • Qt Lighthouse学习(二),就是QPA(Qt Platform Abstraction) 项目的名字

    上一次关注Qt Lighthouse是在6月初,可是现在都8月底了。时间真快...

    Lighthouse 是 QPA(Qt Platform Abstraction) 项目的名字,它使得将Qt移植到新的平台变得比较简单。尽管现在它已经完全融入到了Qt主干代码中,lighthouse作为独立项目已经不复存在了,但本文中,我们继续使用这个名字(虽然已不太恰当)。

    QPA 抽象了什么?

    不妨看看QPA前后,有何不同:

    之前

    考虑一下,传统的Qt是如何实现图形界面的夸平台:

    • 针对不同的窗口系统(WS)定义相应的宏: Q_WS_*

     

    Q_WS_X11
    Q_WS_MAC
    Q_WS_QWS
    Q_WS_WIN
    Q_WS_S60
    • 代码中夹杂大量的编译预处理指令 (处理小段)

     

    #if defined(Q_WS_X11)
    ...
    #elif defined(Q_WS_MAC)
    ...
    #elif defined(Q_WS_WIN)
    ...
    #endif
    • 各个窗口系统相关的代码文件 (处理大段)

     

    qapplication_x11.cpp
    qapplication_win.cpp
    qapplication_s60.cpp
    qapplication_mac.mm
    qapplication_qws.cpp
    ...
    qwidget_win.cpp
    qwidget_qws.cpp
    qwidget_mac.cpp
    qwidget_x11.cpp
    ...
    • src/gui/kernel.pri 等工程文件内,控制哪些文件参与编译

     

    win32 {
    ...
    }
    symbian {
    ...
    }
    unix:x11 {
    ...
    }

    这一切这意味这什么??

    如果我们想在这个基础上支持一个新的窗口系统,比如wayland,需要

    • 添加平台相关的宏,代码中针对该窗口再扩充 #if #elif #endif

    • 添加平台相关的文件,扩充 **.pri 文件使其融入Qt
    • ...

    总之,需要对Qt的代码进行大量的修改。这一切使得将Qt移植到新的窗口系统中,变得不是那么容易。

    之后

    QPA 定义了一套接口,而后,将窗口系统相关的代码放到插件中:

    • src/plugins/platforms/xlib/*
    • src/plugins/platforms/wayland/*
    • src/plugins/platforms/cocoa/*

    这时,如果我们想支持一个新的窗口系统,怎么办?只需要编写一个新的插件,而Qt自身的代码则不需要任何改变。

    (当然,编写插件本身还是很有难度的,哈...)

    QPA源码结构

    为了使插件能供工作,Qt中需要提供有相应的加载接口,在Qt源码中搜索*_qpa.h*_qpa.cpp *_qpa_p.h 即可找到所有(fixme)和 qpa有关的代码:

    • QTDIR/src/opengl
      • qgl_qpa.cpp
    • QTDIR/src/gui
      • painting
        • qcolormap_qpa.cpp
        • qpaintdevice_qpa.cpp
      • image
        • qpixmap_qpa.cpp
      • egl
        • qegl_qpa.cpp
      • kernel
        • qplatformintegrationplugin_qpa.cpp
        • qplatformcursor_qpa.cpp
        • qwidget_qpa.cpp
        • ...
      • text
        • qfontengine_qpa.cpp
        • qfontengine_qpa_p.h
        • ...

    可以看到代码集中在 gui/kernel 部分;除此外,和字体相关gui/text,和绘图相关gui/painting、gui/image、gui/egl,和opengl相关

    QPA结构

    QPlatformIntegration

    这个应该算是 QPA 的核心了,

    • 它是QApplication(准确地说是QApplicationPrivate)的成员

     

    class Q_GUI_EXPORT QApplicationPrivate : public QCoreApplicationPrivate
    {
    ...
        static QPlatformIntegration *platform_integration;
    ...
    • 在初始化QAppliction时它会被创建

     

    QApplication::QApplication()
      QApplicationPrivate::construct()
       qt_init()
         init_platform()
           QPlatfromIntegrationFactory::create()
    • 它是所有窗口系统相关函数的入口点

     

    class Q_GUI_EXPORT QPlatformIntegration
    {
    public:

    GraphicsSystem functions

     

    virtual QPixmapData *createPixmapData()

     

    virtual QPlatformWindow *createPlatformWindow()

     

    virtual QWindowSurface *createWindowSurface()

    Window System functions

     

    virtual QList<QPlatformScreen *> screens()

     

    virtual void moveToScreen()

     

    virtual bool isVirtualDesktop()

     

    virtual QPixmap grabWindow()

    Deeper window system integrations

     

    virtual QPlatformFontDatabase *fontDatabase()

     

    virtual QPlatformClipboard *clipboard()

    ...

    这样一来:

    当你在程序中

    它会向QPlatformIntegration请求

    使用QWidget时

    给我一个窗口(QPlatformWindow)及绘图区域(QWindowSurface)

    使用QPixmap时

    给我一个位图的后端(QPixmapData)

    使用QFont时

    给我字体数据信息(QPlatformFontDatabase)

    使用QGLWidget时

    给我一个窗口

    ...

    ...

    QPlatformWindow 与 QWindowSurface

    QPlatformWindow

    窗口
    负责窗口的几何尺寸
    可以是另一个窗口的子窗口

    QWindowSurface

    窗口绘图区域(drawing area of a window)
    它来决定使用哪一个paintEngine
    将像素Push到屏幕上

    相对而言,QPlatformWindow 出现的比较晚一点(见Say hello to QPlatformWindow一文)之所以。之所以分离开来,原因见Remodelling the Lighthouse

    QPlatformScreen

    • 代表屏幕(显示器)
    • 它提供的api对应用程序来说是只读的
    • 用来计算分辨率 dpi

     

    class Q_GUI_EXPORT QPlatformScreen : public QObject
    {
    ...
        virtual QRect geometry() const = 0;
        virtual QRect availableGeometry() const {return geometry();}
        virtual int depth() const = 0;
        virtual QImage::Format format() const = 0;
        virtual QSize physicalSize() const;

    QPixmapData

    为什么要有这个东西?

    通常我们似乎都不怎么区分QImage和QPixmap,尽管在Manual中很大的篇幅在描述这二者的区别。

    设计目的和用途(一个是IO和像素操作,一个是屏幕显示):

    • QImage is designed and optimized for I/O, and for direct pixel access and manipulation
    • while QPixmap is designed and optimized for showing images on screen.

    典型的用途:

    • Typically, the QImage class is used to load an image file, optionally manipulating the image data, before the QImage object is converted into a QPixmap to be shown on screen.
    • Alternatively, if no manipulation is desired, the image file can be loaded directly into a QPixmap.

    与QImage不同,QPixmap 是平台相关的

    • Note that the pixel data in a pixmap is internal and is managed by the underlying window system.

    于是它的后端需要由各个窗口系统来提供也就不足为奇了。

    QPlatformFontDatabase

    提供字体信息

    详见Fonts in Lighthouse一文。

    其他

    • QPlatformClipboard
    • QPlatformCursor
    • ...

    同前面几个一样,从名字上容易看出是做什么的。

    参考

    http://www.cppblog.com/lauer3912/archive/2011/09/15/155888.html

  • 相关阅读:
    ATCoder code festival 2016 qual C
    2019.10.26模拟赛
    2019.10.24模拟赛
    狄利克雷卷积和莫比乌斯反演学习笔记
    ljq的互测の题解
    noi.ac #39
    noi.ac #741 code
    noi.ac #65 triangle
    让别人也可以访问你电脑上的ASP.NET MVC创建的网站
    ASP.NET MVC 开发中遇到的两个小问题
  • 原文地址:https://www.cnblogs.com/findumars/p/6361980.html
Copyright © 2011-2022 走看看