Merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/dpr into lp:ubuntu-ui-toolkit/staging

Proposed by Gerry Boland
Status: Merged
Approved by: Zsombor Egri
Approved revision: 1205
Merged at revision: 1605
Proposed branch: lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/dpr
Merge into: lp:ubuntu-ui-toolkit/staging
Diff against target: 1044 lines (+747/-26)
22 files modified
debian/control (+5/-0)
src/Ubuntu/Components/plugin/ucqquickimageextension.cpp (+23/-3)
src/Ubuntu/Components/plugin/ucubuntushape.cpp (+17/-13)
src/Ubuntu/Components/plugin/ucunits.cpp (+46/-5)
src/Ubuntu/Components/plugin/ucunits.h (+1/-0)
tests/unit/add_makecheck.pri (+12/-1)
tests/unit/custom_qpa/README (+15/-0)
tests/unit/custom_qpa/custom.json (+3/-0)
tests/unit/custom_qpa/custom_qpa.pro (+15/-0)
tests/unit/custom_qpa/main.cpp (+54/-0)
tests/unit/custom_qpa/qcustombackingstore.cpp (+64/-0)
tests/unit/custom_qpa/qcustombackingstore.h (+55/-0)
tests/unit/custom_qpa/qcustomintegration.cpp (+112/-0)
tests/unit/custom_qpa/qcustomintegration.h (+74/-0)
tests/unit/runtest.sh (+2/-0)
tests/unit/tst_units/dpr1/dpr1.pro (+3/-0)
tests/unit/tst_units/dpr2/dpr2.pro (+3/-0)
tests/unit/tst_units/dpr2/tst_units_dpr2.cpp (+143/-0)
tests/unit/tst_units/dpr3/dpr3.pro (+3/-0)
tests/unit/tst_units/dpr3/tst_units_dpr3.cpp (+88/-0)
tests/unit/tst_units/tst_units.pro (+6/-3)
tests/unit/unit.pro (+3/-1)
To merge this branch: bzr merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/dpr
Reviewer Review Type Date Requested Status
Zsombor Egri Approve
PS Jenkins bot continuous-integration Approve
Loïc Molinari (community) Approve
Gerry Boland (community) Needs Information
Review via email: mp+256470@code.launchpad.net

This proposal supersedes a proposal from 2015-04-16.

Commit message

Compensate for Qt's device pixel ratio multiplier

Description of the change

Compensate for Qt's device pixel ratio multiplier

The UITK has flexible UI scaling support through the use of Grid Units, where one can set a grid unit to be an integer number of pixels, and the whole UI adopts to suit this. GRID_UNIT_PX=10 is the way to set this.

Qt however has its own scaling solution: QScreen::devicePixelRatio->qreal which is a multiplier applied internally to all sizing/positioning calculations. Only integer values are well supported, so 1,2,3... are the options, resulting in a x2, x3 scaling of the entire UI. For linux and X11, devicePixelRatio is specified with QT_DEVICE_PIXEL_RATIO=2. In this case, if a QML item is set to have height 100, it will be drawn 200 pixels high (but QML has no idea of this, it is still 100 in height)

This latter solution works for all Qt apps, whereas Grid units only apply to UITK-based apps. For a HighDPI desktop, we want to use both solutions.

However these two scaling solutions are cumulative. Should one set
QT_DEVICE_PIXEL_RATIO=2 GRID_UNIT_PX=16
then a box of height units.gu(1) will be drawn 32 physical pixels high.

The intention of this MR is to guarantee that GRID_UNIT_PX corresponds to physical pixels, no matter what QScreen::devicePixelRatio returns. To do this, it divides units.{gu,dp} by devicePixelRatio, so that when Qt multiplies it by devicePixelRatio again on draw, the desired physical pixel size is obtained.

To test, open the gallery with these 2 different envs:
QT_DEVICE_PIXEL_RATIO=1 GRID_UNIT_PX=16
QT_DEVICE_PIXEL_RATIO=2 GRID_UNIT_PX=16

Some visual inconsistencies at small GU values are due to exact font rendering sizes and some rounding issues causing off-by-one positioning errors. QT_DEVICE_PIXEL_RATIO=2 GRID_UNIT_PX=8 is not a realistic choice however, likely would only switch to DPR2 when GU>=16.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

Ok, think this is ready for review. I added tests where I could, but would appreciate feedback on how I could test more.

Revision history for this message
Gerry Boland (gerboland) wrote :

+++ modules/Ubuntu/Components/plugin/ucunits.h
+ float devicePixelRatio() const;
should I worry about ABI breaking?

review: Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Loïc Molinari (loic.molinari) wrote :

Just a quick comment before going deeper in the review, the ProgressBar is broken because ucubuntushapeoverlay.cpp hasn't been modified.

review: Needs Fixing
Revision history for this message
Gerry Boland (gerboland) wrote :

Thanks for the initial look, no idea how I missed that overlay issue, it's fixed now

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Loïc Molinari (loic.molinari) wrote :

> +++ modules/Ubuntu/Components/plugin/ucunits.h
> + float devicePixelRatio() const;
> should I worry about ABI breaking?

No worries, it's not an ABI break. And actually we don't care about ABI breaks since we don't export the shared object as a lib.

Revision history for this message
Loïc Molinari (loic.molinari) wrote :

> > +++ modules/Ubuntu/Components/plugin/ucunits.h
> > + float devicePixelRatio() const;
> > should I worry about ABI breaking?
>
> No worries, it's not an ABI break. And actually we don't care about ABI
> breaks since we don't export the shared object as a lib.

(Thinking about it the added floating-point value in the class would be an ABI break if we'd expose the lib)

Revision history for this message
Loïc Molinari (loic.molinari) wrote :
Download full text (3.7 KiB)

Good stuff. Here is a bunch of questions and remarks.

1)
In the shape, storing the radius as device-independent pixel like that

- float radius = UCUnits::instance().gridUnit() * (m_radius == Small ? smallRadiusGU : mediumRadiusGU);
- const float scaledDownRadius = qMin(itemSize.width(), itemSize.height()) * dpr * 0.5f * 0.8f;
+ float radius = UCUnits::instance().gu((m_radius == Small ? smallRadiusGU : mediumRadiusGU));
+ const float scaledDownRadius = qMin(itemSize.width(), itemSize.height()) * 0.5f * 0.8f;

would remove the need to multiply the item size by the dpr for the shape coordinates attributes in updateVertices() (for both UbuntuShape and UbuntuShapeOverlay). That would require to do change updateMaterial() though, but in a less intrusive way IMO:

@@ -1217,16 +1218,18 @@
         materialData->sourceOpacity = 0;
     }

+ const float physicalRadius = UCUnits::instance().devicePixelRatio() * radius;
+
     // Mapping of radius size range from [0, 4] to [0, 1] with clamping, plus quantization.
     const float start = 0.0f + radiusSizeOffset;
     const float end = 4.0f + radiusSizeOffset;
     materialData->distanceAAFactor = qMin(
- (radius / (end - start)) - (start / (end - start)), 1.0f) * 255.0f;
+ (physicalRadius / (end - start)) - (start / (end - start)), 1.0f) * 255.0f;

     // When the radius is equal to radiusSizeOffset (which means radius size is 0), no aspect is
     // flagged so that a dedicated (statically flow controlled) shaved off shader can be used for
     // optimal performance.
- if (radius > radiusSizeOffset) {
+ if (physicalRadius > radiusSizeOffset) {
         const quint8 aspectFlags[] = {
             ShapeMaterial::Data::Flat, ShapeMaterial::Data::Inset,
             ShapeMaterial::Data::Inset | ShapeMaterial::Data::Pressed

2) The previous change would allow to move the devicePixelRatio retrieval in updateGeometryNode() to the "if (m_flags & DirtySourceTransform) {" scope.

3)
- Q_INVOKABLE float dp(float value);
- Q_INVOKABLE float gu(float value);
+ Q_INVOKABLE float dp(const float value);
+ Q_INVOKABLE float gu(const float value);

Using const for value parameters (not for reference or pointer parameters) isn't a common practice in the toolkit (neither in Qt AFAIK). Is there a particular reason for it?

4) Wouldn't it be better (faster) to inline UCUnits::devicePixelRatio() definition in the header?

5) Talking about UCUnits::devicePixelRatio(), why do we have to expose it instead of using QGuiApplication::devicePixelRation() or QWindow::devicePixelRatio() directly? Same question for the "manual" retrieval of QT_DEVICE_PIXEL_RATIO in UCUnits constructor.

6) UCUnits::gu() and UCUnits:dp() returns "qRound(value * m_gridUnit) / m_devicePixelRatio", I'm wondering if the division should be applied before the rounding?

7) It took me some time to figure out the logic because I didn't realize we had to support QtWidgets as well. I think we'd better explain the whole decision somewhere in the project, either in the README or in the UCUnits module. I'd tend to go for a good explanation in the ucunits.cpp module documentation maybe adding toolkit implementation...

Read more...

review: Needs Fixing
Revision history for this message
Gerry Boland (gerboland) wrote :
Download full text (3.7 KiB)

> Good stuff. Here is a bunch of questions and remarks.
>
> 1)
> In the shape, storing the radius as device-independent pixel like that
>
> - float radius = UCUnits::instance().gridUnit() * (m_radius == Small ?
> smallRadiusGU : mediumRadiusGU);
> - const float scaledDownRadius = qMin(itemSize.width(), itemSize.height())
> * dpr * 0.5f * 0.8f;
> + float radius = UCUnits::instance().gu((m_radius == Small ? smallRadiusGU
> : mediumRadiusGU));
> + const float scaledDownRadius = qMin(itemSize.width(), itemSize.height())
> * 0.5f * 0.8f;
>
> would remove the need to multiply the item size by the dpr for the shape
> coordinates attributes in updateVertices() (for both UbuntuShape and
> UbuntuShapeOverlay). That would require to do change updateMaterial() though,
> but in a less intrusive way IMO:
<snip>
Done!

> 2) The previous change would allow to move the devicePixelRatio retrieval in
> updateGeometryNode() to the "if (m_flags & DirtySourceTransform) {" scope.
Done

> 3)
> - Q_INVOKABLE float dp(float value);
> - Q_INVOKABLE float gu(float value);
> + Q_INVOKABLE float dp(const float value);
> + Q_INVOKABLE float gu(const float value);
>
> Using const for value parameters (not for reference or pointer parameters)
> isn't a common practice in the toolkit (neither in Qt AFAIK). Is there a
> particular reason for it?
I had thought compiler could optimize a little better with this, but I'm told it's of no use. Reverted.

> 4) Wouldn't it be better (faster) to inline UCUnits::devicePixelRatio()
> definition in the header?
>
> 5) Talking about UCUnits::devicePixelRatio(), why do we have to expose it
> instead of using QGuiApplication::devicePixelRation() or
> QWindow::devicePixelRatio() directly? Same question for the "manual" retrieval
> of QT_DEVICE_PIXEL_RATIO in UCUnits constructor.

Yeah I got rid of this. I had mainly added it to UCUnits to ease mocking it for testing. Instead I've added a custom minimal QPA plugin to mock the value of devicePixelRatio(). So UCUnits API has be left unchanged by this MR.

>
> 6) UCUnits::gu() and UCUnits:dp() returns "qRound(value * m_gridUnit) /
> m_devicePixelRatio", I'm wondering if the division should be applied before
> the rounding?

I left the division after the rounding as Qt will take this value, multiply it by devicePixelRatio to calculate the physical pixels. I.e.
physicalPixels = [qRound(value * m_gridUnit) / m_devicePixelRatio] * m_devicePixelRatio
should be more correct than
physicalPixels = qRound(value * m_gridUnit / m_devicePixelRatio) * m_devicePixelRatio

> 7) It took me some time to figure out the logic because I didn't realize we
> had to support QtWidgets as well. I think we'd better explain the whole
> decision somewhere in the project, either in the README or in the UCUnits
> module. I'd tend to go for a good explanation in the ucunits.cpp module
> documentation maybe adding toolkit implementation details in there in a "non-
> exposed" comment if needed. We should also agree on a better naming for the
> units, currently there are grid units, device pixels, value density
> independent pixels, actual pixels, physical pixels, etc, it's very confusing.
> I...

Read more...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1195. By Gerry Boland

Add missing build dependencies

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
1196. By Gerry Boland

Bump version

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
1197. By Gerry Boland

Merge staging and fix conflicts

1198. By Gerry Boland

Revert rev 1196

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
1199. By Gerry Boland

Merge staging, fix a conflict

1200. By Gerry Boland

Undo changes to paths for gallery launcher

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1201. By Gerry Boland

Merge staging

Revision history for this message
Zsombor Egri (zsombi) wrote :

Small fixes, and we're good.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Loïc Molinari (loic.molinari) wrote :

I guess there's a merge problem, m_relativeRadius is defined two times in UCUbuntuShape initialisation list. Apart from that, everything looks good to me now.

Thanks for the changes and sorry for the delay to take a look back at that...

review: Approve
1202. By Gerry Boland

Fix build fail - variable inited twice

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
1203. By Gerry Boland

Merge staging again

1204. By Gerry Boland

Merge staging again

1205. By Gerry Boland

Revert accidental changes to examples/ubuntu-ui-toolkit-gallery/po/nl.po

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Zsombor Egri (zsombi) wrote :

Good to go now! Thanks allot!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/control'
--- debian/control 2015-07-10 05:40:21 +0000
+++ debian/control 2015-08-12 11:28:41 +0000
@@ -45,6 +45,11 @@
45 suru-icon-theme,45 suru-icon-theme,
46 uuid-runtime,46 uuid-runtime,
47 python3-sphinx,47 python3-sphinx,
48 libfontconfig1-dev,
49 libfreetype6-dev,
50 libmtdev-dev,
51 libudev-dev,
52 libxrender-dev
48Standards-Version: 3.9.453Standards-Version: 3.9.4
49Homepage: https://launchpad.net/ubuntu-ui-toolkit54Homepage: https://launchpad.net/ubuntu-ui-toolkit
50# If you aren't a member of ~ubuntu-sdk-team but need to upload packaging55# If you aren't a member of ~ubuntu-sdk-team but need to upload packaging
5156
=== modified file 'src/Ubuntu/Components/plugin/ucqquickimageextension.cpp'
--- src/Ubuntu/Components/plugin/ucqquickimageextension.cpp 2014-11-24 13:14:35 +0000
+++ src/Ubuntu/Components/plugin/ucqquickimageextension.cpp 2015-08-12 11:28:41 +0000
@@ -19,6 +19,7 @@
19#include <QtCore/QFile>19#include <QtCore/QFile>
20#include <QtCore/QFileInfo>20#include <QtCore/QFileInfo>
21#include <QtCore/QDir>21#include <QtCore/QDir>
22#include <QtGui/QGuiApplication>
22#include <QtQuick/private/qquickimagebase_p.h>23#include <QtQuick/private/qquickimagebase_p.h>
2324
24#include "ucqquickimageextension.h"25#include "ucqquickimageextension.h"
@@ -78,8 +79,18 @@
78 QString selectedFilePath = resolved.mid(separatorPosition+1);79 QString selectedFilePath = resolved.mid(separatorPosition+1);
7980
80 if (scaleFactor == "1") {81 if (scaleFactor == "1") {
81 // No scaling. Just pass the file as is.82 if (qFuzzyCompare(qGuiApp->devicePixelRatio(), (qreal)1.0)
82 m_image->setSource(QUrl::fromLocalFile(selectedFilePath));83 || selectedFilePath.endsWith(".svg") || selectedFilePath.endsWith(".svgz")) {
84 // No scaling necessary. Just pass the file as is.
85 m_image->setSource(QUrl::fromLocalFile(selectedFilePath));
86 } else {
87 // Need to scale the pixel-based image to suit the devicePixelRatio setting ourselves.
88 // If we let Qt do it, Qt will not choose the UITK-supported "@gu" scaled images.
89 m_image->setSource(QUrl("image://scaling/1/" + selectedFilePath));
90 // explicitly set the source size in the QQuickImageBase, this persuades it that the
91 // supplied image is suitable for the current devicePixelRatio.
92 m_image->setSourceSize(m_image->sourceSize());
93 }
83 } else {94 } else {
84 // Prepend "image://scaling" for the image to be loaded by UCScalingImageProvider.95 // Prepend "image://scaling" for the image to be loaded by UCScalingImageProvider.
85 if (!m_source.path().endsWith(".sci")) {96 if (!m_source.path().endsWith(".sci")) {
@@ -100,7 +111,13 @@
100 rewrittenSciFile->setFileTemplate(QDir::tempPath() + QDir::separator() + "XXXXXX.sci");111 rewrittenSciFile->setFileTemplate(QDir::tempPath() + QDir::separator() + "XXXXXX.sci");
101 rewrittenSciFile->open();112 rewrittenSciFile->open();
102 QTextStream output(rewrittenSciFile);113 QTextStream output(rewrittenSciFile);
103 rewritten = rewriteSciFile(selectedFilePath, scaleFactor, output);114
115 if (qFuzzyCompare(qGuiApp->devicePixelRatio(), (qreal)1.0)) {
116 rewritten = rewriteSciFile(selectedFilePath, scaleFactor, output);
117 } else {
118 QString scaleFactorInDevicePixels = QString::number(scaleFactor.toFloat() / qGuiApp->devicePixelRatio());
119 rewritten = rewriteSciFile(selectedFilePath, scaleFactorInDevicePixels, output);
120 }
104 rewrittenSciFile->close();121 rewrittenSciFile->close();
105122
106 s_rewrittenSciFiles.insert(m_source, QSharedPointer<QTemporaryFile>(rewrittenSciFile));123 s_rewrittenSciFiles.insert(m_source, QSharedPointer<QTemporaryFile>(rewrittenSciFile));
@@ -112,6 +129,9 @@
112 m_image->setSource(m_source);129 m_image->setSource(m_source);
113 }130 }
114 }131 }
132 // explicitly set the source size in the QQuickImageBase, this persuades it that the
133 // supplied image is suitable for the current devicePixelRatio.
134 m_image->setSourceSize(m_image->sourceSize());
115 }135 }
116}136}
117137
118138
=== modified file 'src/Ubuntu/Components/plugin/ucubuntushape.cpp'
--- src/Ubuntu/Components/plugin/ucubuntushape.cpp 2015-08-06 13:16:24 +0000
+++ src/Ubuntu/Components/plugin/ucubuntushape.cpp 2015-08-12 11:28:41 +0000
@@ -308,10 +308,7 @@
308 setFlag(ItemHasContents);308 setFlag(ItemHasContents);
309 QObject::connect(&UCUnits::instance(), SIGNAL(gridUnitChanged()), this,309 QObject::connect(&UCUnits::instance(), SIGNAL(gridUnitChanged()), this,
310 SLOT(_q_gridUnitChanged()));310 SLOT(_q_gridUnitChanged()));
311 const float gridUnit = UCUnits::instance().gridUnit();311 _q_gridUnitChanged();
312 setImplicitWidth(implicitWidthGU * gridUnit);
313 setImplicitHeight(implicitHeightGU * gridUnit);
314 update();
315}312}
316313
317/*! \qmlproperty string UbuntuShape::radius314/*! \qmlproperty string UbuntuShape::radius
@@ -998,9 +995,9 @@
998995
999void UCUbuntuShape::_q_gridUnitChanged()996void UCUbuntuShape::_q_gridUnitChanged()
1000{997{
1001 const float gridUnit = UCUnits::instance().gridUnit();998 const float gridUnitInDevicePixels = UCUnits::instance().gridUnit() / qGuiApp->devicePixelRatio();
1002 setImplicitWidth(implicitWidthGU * gridUnit);999 setImplicitWidth(implicitWidthGU * gridUnitInDevicePixels);
1003 setImplicitHeight(implicitHeightGU * gridUnit);1000 setImplicitHeight(implicitHeightGU * gridUnitInDevicePixels);
1004 update();1001 update();
1005}1002}
10061003
@@ -1162,13 +1159,15 @@
1162 sourceTextureRect = sourceTexture->normalizedTextureSubRect();1159 sourceTextureRect = sourceTexture->normalizedTextureSubRect();
1163 }1160 }
1164 if (m_flags & DirtySourceTransform) {1161 if (m_flags & DirtySourceTransform) {
1162 const float dpr = qGuiApp->devicePixelRatio();
1163
1165 if (m_flags & SourceApiSet) {1164 if (m_flags & SourceApiSet) {
1166 updateSourceTransform(itemSize.width(), itemSize.height(), m_sourceFillMode,1165 updateSourceTransform(itemSize.width() * dpr, itemSize.height() * dpr, m_sourceFillMode,
1167 m_sourceHorizontalAlignment, m_sourceVerticalAlignment,1166 m_sourceHorizontalAlignment, m_sourceVerticalAlignment,
1168 sourceTexture->textureSize());1167 sourceTexture->textureSize());
1169 } else {1168 } else {
1170 FillMode imageFillMode = (m_flags & Stretched) ? Stretch : PreserveAspectCrop;1169 FillMode imageFillMode = (m_flags & Stretched) ? Stretch : PreserveAspectCrop;
1171 updateSourceTransform(itemSize.width(), itemSize.height(), imageFillMode,1170 updateSourceTransform(itemSize.width() * dpr, itemSize.height() * dpr, imageFillMode,
1172 m_imageHorizontalAlignment, m_imageVerticalAlignment,1171 m_imageHorizontalAlignment, m_imageVerticalAlignment,
1173 sourceTexture->textureSize());1172 sourceTexture->textureSize());
1174 }1173 }
@@ -1198,13 +1197,15 @@
1198 // accordingly. The shape was using a fixed image for the corner before switching to a1197 // accordingly. The shape was using a fixed image for the corner before switching to a
1199 // distance field, since the corner wasn't taking the whole image (ending at ~80%) we need1198 // distance field, since the corner wasn't taking the whole image (ending at ~80%) we need
1200 // to take that into account when the size is scaled down.1199 // to take that into account when the size is scaled down.
1201 radius = UCUnits::instance().gridUnit() * radiusGuMap[m_radius];1200 radius = UCUnits::instance().gridUnit() * radiusGuMap[m_radius]
1201 / qGuiApp->devicePixelRatio();
1202 const float scaledDownRadius = qMin(itemSize.width(), itemSize.height()) * 0.5f * 0.8f;1202 const float scaledDownRadius = qMin(itemSize.width(), itemSize.height()) * 0.5f * 0.8f;
1203 if (radius > scaledDownRadius) {1203 if (radius > scaledDownRadius) {
1204 radius = scaledDownRadius;1204 radius = scaledDownRadius;
1205 }1205 }
1206 } else {1206 } else {
1207 radius = qMin(itemSize.width(), itemSize.height()) * 0.5f * (m_relativeRadius * 0.01f);1207 radius = qMin(itemSize.width(), itemSize.height()) * 0.5f * (m_relativeRadius * 0.01f)
1208 / qGuiApp->devicePixelRatio();
1208 }1209 }
12091210
1210 updateMaterial(node, radius, shapeTextureId, sourceTexture && m_sourceOpacity);1211 updateMaterial(node, radius, shapeTextureId, sourceTexture && m_sourceOpacity);
@@ -1284,16 +1285,19 @@
1284 materialData->sourceOpacity = 0;1285 materialData->sourceOpacity = 0;
1285 }1286 }
12861287
1288 const float physicalRadius = radius * qGuiApp->devicePixelRatio();
1289
1287 // Mapping of radius size range from [0, 4] to [0, 1] with clamping, plus quantization.1290 // Mapping of radius size range from [0, 4] to [0, 1] with clamping, plus quantization.
1288 const float start = 0.0f + radiusSizeOffset;1291 const float start = 0.0f + radiusSizeOffset;
1289 const float end = 4.0f + radiusSizeOffset;1292 const float end = 4.0f + radiusSizeOffset;
1293
1290 materialData->distanceAAFactor =1294 materialData->distanceAAFactor =
1291 qMin((radius / (end - start)) - (start / (end - start)), 1.0f) * 255.0f;1295 qMin((physicalRadius / (end - start)) - (start / (end - start)), 1.0f) * 255.0f;
12921296
1293 // When the radius is equal to radiusSizeOffset (which means radius size is 0), no aspect is1297 // When the radius is equal to radiusSizeOffset (which means radius size is 0), no aspect is
1294 // flagged so that a dedicated (statically flow controlled) shaved off shader can be used for1298 // flagged so that a dedicated (statically flow controlled) shaved off shader can be used for
1295 // optimal performance.1299 // optimal performance.
1296 if (radius > radiusSizeOffset) {1300 if (physicalRadius > radiusSizeOffset) {
1297 const quint8 aspectFlags[] = {1301 const quint8 aspectFlags[] = {
1298 ShapeMaterial::Data::Flat, ShapeMaterial::Data::Inset, ShapeMaterial::Data::DropShadow,1302 ShapeMaterial::Data::Flat, ShapeMaterial::Data::Inset, ShapeMaterial::Data::DropShadow,
1299 ShapeMaterial::Data::Inset | ShapeMaterial::Data::Pressed1303 ShapeMaterial::Data::Inset | ShapeMaterial::Data::Pressed
13001304
=== modified file 'src/Ubuntu/Components/plugin/ucunits.cpp'
--- src/Ubuntu/Components/plugin/ucunits.cpp 2015-03-03 13:47:48 +0000
+++ src/Ubuntu/Components/plugin/ucunits.cpp 2015-08-12 11:28:41 +0000
@@ -24,6 +24,8 @@
24#include <QtCore/QDir>24#include <QtCore/QDir>
25#include <QtCore/QRegularExpression>25#include <QtCore/QRegularExpression>
26#include <QtCore/qmath.h>26#include <QtCore/qmath.h>
27#include <QtGui/QGuiApplication>
28#include <QtGui/QScreen>
2729
28#define ENV_GRID_UNIT_PX "GRID_UNIT_PX"30#define ENV_GRID_UNIT_PX "GRID_UNIT_PX"
29#define DEFAULT_GRID_UNIT_PX 831#define DEFAULT_GRID_UNIT_PX 8
@@ -62,10 +64,46 @@
6264
63 \sa {Resolution Independence}65 \sa {Resolution Independence}
64*/66*/
67
68/*
69 * Note on the interaction between GRID_UNIT_PX and QT_DEVICE_PIXEL_RATIO
70 *
71 * In Qt5.4 there is a single means to scale the UI: the QT_DEVICE_PIXEL_RATIO environment
72 * variable. This accepts only integer values, thus allowing a x2 or x3 scaling of any
73 * Qt-based UI, that includes QWidget as well as any QML UI.
74 *
75 * Setting QT_DEVICE_PIXEL_RATIO=2 implies one density-independent pixel corresponds to 2
76 * physical pixels. Developers describe their UI in terms of density-independent pixels.
77 * Qt scales accordingly.
78 *
79 * The Ubuntu UI Toolkit has solved the scaling problem with the GRID_UNIT_PX variable.
80 * It offers more flexibility, but only scales QML applications written to use the UITK
81 * (since it uses this Units class) as it is built on top of QML.
82 *
83 * There are additional areas in Qt where QT_DEVICE_PIXEL_RATIO causes correct scaling which
84 * GRID_UNIT_PX cannot, for example:
85 * 1. cacheBuffer for ListView/GridViews - specified in density-independent pixels
86 * 2. gesture recognition matches what is on screen better, as it is density-independent
87 * pixel aware
88 *
89 * In order to get the best of both worlds, Ubuntu will set both GRID_UNIT_PX and
90 * QT_DEVICE_PIXEL_RATIO. Thus all Qt apps will scale reasonably well, with UITK-based apps
91 * scaling perfectly for any desired scale (i.e. non-integer scales).
92 *
93 * However UITK developers can just use this Units class as usual, and will be almost totally
94 * isolated from Qt's own scaling concept.
95 */
96
65UCUnits::UCUnits(QObject *parent) :97UCUnits::UCUnits(QObject *parent) :
66 QObject(parent)98 QObject(parent),
99 m_devicePixelRatio(qGuiApp->devicePixelRatio())
67{100{
68 m_gridUnit = getenvFloat(ENV_GRID_UNIT_PX, DEFAULT_GRID_UNIT_PX);101 // If GRID_UNIT_PX set, always use it. If not, 1GU := DEFAULT_GRID_UNIT_PX * m_devicePixelRatio
102 if (qEnvironmentVariableIsSet(ENV_GRID_UNIT_PX)) {
103 m_gridUnit = getenvFloat(ENV_GRID_UNIT_PX, DEFAULT_GRID_UNIT_PX);
104 } else {
105 m_gridUnit = DEFAULT_GRID_UNIT_PX * m_devicePixelRatio;
106 }
69}107}
70108
71/*!109/*!
@@ -89,14 +127,15 @@
89127
90 Returns the number of pixels \a value density independent pixels correspond to.128 Returns the number of pixels \a value density independent pixels correspond to.
91*/129*/
130// Density-independent pixels (and not physical pixels) because Qt sizes in terms of density-independent pixels.
92float UCUnits::dp(float value)131float UCUnits::dp(float value)
93{132{
94 const float ratio = m_gridUnit / DEFAULT_GRID_UNIT_PX;133 const float ratio = m_gridUnit / DEFAULT_GRID_UNIT_PX;
95 if (value <= 2.0) {134 if (value <= 2.0) {
96 // for values under 2dp, return only multiples of the value135 // for values under 2dp, return only multiples of the value
97 return qRound(value * qFloor(ratio));136 return qRound(value * qFloor(ratio)) / m_devicePixelRatio;
98 } else {137 } else {
99 return qRound(value * ratio);138 return qRound(value * ratio) / m_devicePixelRatio;
100 }139 }
101}140}
102141
@@ -105,9 +144,11 @@
105144
106 Returns the number of pixels \a value grid units correspond to.145 Returns the number of pixels \a value grid units correspond to.
107*/146*/
147// Density-independent pixels (and not physical pixels) because Qt sizes in terms of density-independent pixels.
148
108float UCUnits::gu(float value)149float UCUnits::gu(float value)
109{150{
110 return qRound(value * m_gridUnit);151 return qRound(value * m_gridUnit) / m_devicePixelRatio;
111}152}
112153
113QString UCUnits::resolveResource(const QUrl& url)154QString UCUnits::resolveResource(const QUrl& url)
114155
=== modified file 'src/Ubuntu/Components/plugin/ucunits.h'
--- src/Ubuntu/Components/plugin/ucunits.h 2013-10-18 08:56:39 +0000
+++ src/Ubuntu/Components/plugin/ucunits.h 2015-08-12 11:28:41 +0000
@@ -53,6 +53,7 @@
53 float gridUnitSuffixFromFileName(const QString &fileName);53 float gridUnitSuffixFromFileName(const QString &fileName);
5454
55private:55private:
56 float m_devicePixelRatio;
56 float m_gridUnit;57 float m_gridUnit;
57};58};
5859
5960
=== modified file 'tests/unit/add_makecheck.pri'
--- tests/unit/add_makecheck.pri 2015-05-19 07:55:27 +0000
+++ tests/unit/add_makecheck.pri 2015-08-12 11:28:41 +0000
@@ -5,4 +5,15 @@
5check.target = check5check.target = check
6check.commands += cd $$_PRO_FILE_PWD_;6check.commands += cd $$_PRO_FILE_PWD_;
7check.commands += env LD_LIBRARY_PATH=$${ROOT_BUILD_DIR}/qml/Ubuntu/Components:$${ROOT_BUILD_DIR}/qml/Ubuntu/Layouts:$${ROOT_BUILD_DIR}/qml/Ubuntu/PerformanceMetrics:$${ROOT_BUILD_DIR}/qml/Ubuntu/Test UITK_TEST_KEEP_RUNNING=17check.commands += env LD_LIBRARY_PATH=$${ROOT_BUILD_DIR}/qml/Ubuntu/Components:$${ROOT_BUILD_DIR}/qml/Ubuntu/Layouts:$${ROOT_BUILD_DIR}/qml/Ubuntu/PerformanceMetrics:$${ROOT_BUILD_DIR}/qml/Ubuntu/Test UITK_TEST_KEEP_RUNNING=1
8check.commands += '$${ROOT_SOURCE_DIR}/tests/unit/runtest.sh "$$shadowed($$_PRO_FILE_PWD_)/$${TARGET}" "$$shadowed($$_PRO_FILE_PWD_)/$${TARGET}" minimal';8
9TEST_COMMAND = '$${ROOT_SOURCE_DIR}/tests/unit/runtest.sh "$$shadowed($$_PRO_FILE_PWD_)/$${TARGET}" "$$shadowed($$_PRO_FILE_PWD_)/$${TARGET}"'
10
11message($$TEST_COMMAND)
12
13# if "CONFIG += custom_qpa" is set, use our custom QPA plugin for the test
14custom_qpa {
15 check.commands += env QT_QPA_PLATFORM_PLUGIN_PATH=$${ROOT_BUILD_DIR}/tests/unit/custom_qpa
16 check.commands += '$$TEST_COMMAND custom';
17} else {
18 check.commands += '$$TEST_COMMAND minimal';
19}
920
=== added directory 'tests/unit/custom_qpa'
=== added file 'tests/unit/custom_qpa/README'
--- tests/unit/custom_qpa/README 1970-01-01 00:00:00 +0000
+++ tests/unit/custom_qpa/README 2015-08-12 11:28:41 +0000
@@ -0,0 +1,15 @@
1In order to correctly test Qt's Device Pixel Ratio system in a
2unit test, one needs to have the QPA plugin for the platform
3support reading the DEVICE_PIXEL_RATIO environment variable.
4
5These unit tests use the "minimal" QPA plugin, which
6unfortunately does not support that variable.
7
8The contents of this directory is a near-complete duplicate of
9"minimal" QPA plugin source from Qt, with added support for the
10DEVICE_PIXEL_RATIO environment variable.
11
12One can use this plugin as follows:
13
14DEVICE_PIXEL_RATIO=2 QT_QPA_PLATFORM_PLUGIN_PATH=$PWD \
15 QT_QPA_PLATFORM=custom qmlscene ~/tmp.qml
016
=== added file 'tests/unit/custom_qpa/custom.json'
--- tests/unit/custom_qpa/custom.json 1970-01-01 00:00:00 +0000
+++ tests/unit/custom_qpa/custom.json 2015-08-12 11:28:41 +0000
@@ -0,0 +1,3 @@
1{
2 "Keys": [ "custom" ]
3}
04
=== added file 'tests/unit/custom_qpa/custom_qpa.pro'
--- tests/unit/custom_qpa/custom_qpa.pro 1970-01-01 00:00:00 +0000
+++ tests/unit/custom_qpa/custom_qpa.pro 2015-08-12 11:28:41 +0000
@@ -0,0 +1,15 @@
1TARGET = qcustom
2TEMPLATE = lib
3
4CONFIG += plugin no_keywords c++11
5
6QT -= gui
7QT += core-private gui-private platformsupport-private
8
9SOURCES = main.cpp \
10 qcustomintegration.cpp \
11 qcustombackingstore.cpp
12HEADERS = qcustomintegration.h \
13 qcustombackingstore.h
14
15OTHER_FILES += custom.json
016
=== added file 'tests/unit/custom_qpa/main.cpp'
--- tests/unit/custom_qpa/main.cpp 1970-01-01 00:00:00 +0000
+++ tests/unit/custom_qpa/main.cpp 2015-08-12 11:28:41 +0000
@@ -0,0 +1,54 @@
1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** In addition, as a special exception, Digia gives you certain additional
27** rights. These rights are described in the Digia Qt LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34
35#include <qpa/qplatformintegrationplugin.h>
36#include "qcustomintegration.h"
37
38class QCustomIntegrationPlugin : public QPlatformIntegrationPlugin
39{
40 Q_OBJECT
41 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "custom.json")
42public:
43 QPlatformIntegration *create(const QString&, const QStringList&);
44};
45
46QPlatformIntegration *QCustomIntegrationPlugin::create(const QString& system, const QStringList& /*paramList*/)
47{
48 if (!system.compare(QLatin1String("custom"), Qt::CaseInsensitive))
49 return new QCustomIntegration();
50
51 return 0;
52}
53
54#include "main.moc"
055
=== added file 'tests/unit/custom_qpa/qcustombackingstore.cpp'
--- tests/unit/custom_qpa/qcustombackingstore.cpp 1970-01-01 00:00:00 +0000
+++ tests/unit/custom_qpa/qcustombackingstore.cpp 2015-08-12 11:28:41 +0000
@@ -0,0 +1,64 @@
1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** In addition, as a special exception, Digia gives you certain additional
27** rights. These rights are described in the Digia Qt LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34
35#include "qcustombackingstore.h"
36#include "qcustomintegration.h"
37#include "qscreen.h"
38#include <qpa/qplatformscreen.h>
39#include <private/qguiapplication_p.h>
40
41
42QCustomBackingStore::QCustomBackingStore(QWindow *window)
43 : QPlatformBackingStore(window)
44{
45}
46
47QPaintDevice *QCustomBackingStore::paintDevice()
48{
49 return &mImage;
50}
51
52void QCustomBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
53{
54 Q_UNUSED(window);
55 Q_UNUSED(region);
56 Q_UNUSED(offset);
57}
58
59void QCustomBackingStore::resize(const QSize &size, const QRegion &)
60{
61 QImage::Format format = QGuiApplication::primaryScreen()->handle()->format();
62 if (mImage.size() != size)
63 mImage = QImage(size, format);
64}
065
=== added file 'tests/unit/custom_qpa/qcustombackingstore.h'
--- tests/unit/custom_qpa/qcustombackingstore.h 1970-01-01 00:00:00 +0000
+++ tests/unit/custom_qpa/qcustombackingstore.h 2015-08-12 11:28:41 +0000
@@ -0,0 +1,55 @@
1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** In addition, as a special exception, Digia gives you certain additional
27** rights. These rights are described in the Digia Qt LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#ifndef QBACKINGSTORE_MINIMAL_H
35#define QBACKINGSTORE_MINIMAL_H
36
37#include <qpa/qplatformbackingstore.h>
38#include <qpa/qplatformwindow.h>
39#include <QtGui/QImage>
40
41class QCustomBackingStore : public QPlatformBackingStore
42{
43public:
44 QCustomBackingStore(QWindow *window);
45 ~QCustomBackingStore() = default;
46
47 QPaintDevice *paintDevice();
48 void flush(QWindow *window, const QRegion &region, const QPoint &offset);
49 void resize(const QSize &size, const QRegion &staticContents);
50
51private:
52 QImage mImage;
53};
54
55#endif
056
=== added file 'tests/unit/custom_qpa/qcustomintegration.cpp'
--- tests/unit/custom_qpa/qcustomintegration.cpp 1970-01-01 00:00:00 +0000
+++ tests/unit/custom_qpa/qcustomintegration.cpp 2015-08-12 11:28:41 +0000
@@ -0,0 +1,112 @@
1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** In addition, as a special exception, Digia gives you certain additional
27** rights. These rights are described in the Digia Qt LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#include "qcustomintegration.h"
35#include "qcustombackingstore.h"
36
37#include <QtGui/private/qguiapplication_p.h>
38#include <qpa/qplatformwindow.h>
39#include <qpa/qplatformfontdatabase.h>
40
41#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
42
43static const char devicePixelRatioEnvironmentVariable[] = "QT_DEVICE_PIXEL_RATIO";
44
45QCustomScreen::QCustomScreen()
46 : mDepth(32), mFormat(QImage::Format_ARGB32_Premultiplied), mDpr(1.0)
47{
48 if (qEnvironmentVariableIsSet(devicePixelRatioEnvironmentVariable)) {
49 bool ok = false;
50 const float dpr = qgetenv(devicePixelRatioEnvironmentVariable).toFloat(&ok);
51 if (ok && dpr > 0) {
52 mDpr = dpr;
53 }
54 }
55}
56
57QCustomIntegration::QCustomIntegration()
58{
59 QCustomScreen *mPrimaryScreen = new QCustomScreen();
60
61 mPrimaryScreen->mGeometry = QRect(0, 0, 240, 320);
62 mPrimaryScreen->mDepth = 32;
63 mPrimaryScreen->mFormat = QImage::Format_ARGB32_Premultiplied;
64
65 screenAdded(mPrimaryScreen);
66}
67
68bool QCustomIntegration::hasCapability(QPlatformIntegration::Capability cap) const
69{
70 switch (cap) {
71 case ThreadedPixmaps: return true;
72 case MultipleWindows: return true;
73 default: return QPlatformIntegration::hasCapability(cap);
74 }
75}
76
77// Dummy font database that does not scan the fonts directory to be
78// used for command line tools like qmlplugindump that do not create windows
79// unless DebugBackingStore is activated.
80class DummyFontDatabase : public QPlatformFontDatabase
81{
82public:
83 void populateFontDatabase() override {}
84};
85
86QPlatformFontDatabase *QCustomIntegration::fontDatabase() const
87{
88 return new DummyFontDatabase;
89}
90
91
92QPlatformWindow *QCustomIntegration::createPlatformWindow(QWindow *window) const
93{
94 QPlatformWindow *w = new QPlatformWindow(window);
95 w->requestActivateWindow();
96 return w;
97}
98
99QPlatformBackingStore *QCustomIntegration::createPlatformBackingStore(QWindow *window) const
100{
101 return new QCustomBackingStore(window);
102}
103
104QAbstractEventDispatcher *QCustomIntegration::createEventDispatcher() const
105{
106 return createUnixEventDispatcher();
107}
108
109QCustomIntegration *QCustomIntegration::instance()
110{
111 return static_cast<QCustomIntegration *>(QGuiApplicationPrivate::platformIntegration());
112}
0113
=== added file 'tests/unit/custom_qpa/qcustomintegration.h'
--- tests/unit/custom_qpa/qcustomintegration.h 1970-01-01 00:00:00 +0000
+++ tests/unit/custom_qpa/qcustomintegration.h 2015-08-12 11:28:41 +0000
@@ -0,0 +1,74 @@
1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** In addition, as a special exception, Digia gives you certain additional
27** rights. These rights are described in the Digia Qt LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#ifndef QPLATFORMINTEGRATION_MINIMAL_H
35#define QPLATFORMINTEGRATION_MINIMAL_H
36
37#include <qpa/qplatformintegration.h>
38#include <qpa/qplatformscreen.h>
39
40class QCustomScreen : public QPlatformScreen
41{
42public:
43 QCustomScreen();
44
45 QRect geometry() const override { return mGeometry; }
46 int depth() const override { return mDepth; }
47 QImage::Format format() const override { return mFormat; }
48 qreal devicePixelRatio() const override { return mDpr; }
49
50public:
51 QRect mGeometry;
52 int mDepth;
53 QImage::Format mFormat;
54 QSize mPhysicalSize;
55 qreal mDpr;
56};
57
58class QCustomIntegration : public QPlatformIntegration
59{
60public:
61 explicit QCustomIntegration();
62 ~QCustomIntegration() = default;
63
64 bool hasCapability(QPlatformIntegration::Capability cap) const override;
65 QPlatformFontDatabase *fontDatabase() const override;
66
67 QPlatformWindow *createPlatformWindow(QWindow *window) const override;
68 QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
69 QAbstractEventDispatcher *createEventDispatcher() const override;
70
71 static QCustomIntegration *instance();
72};
73
74#endif
075
=== modified file 'tests/unit/runtest.sh'
--- tests/unit/runtest.sh 2015-06-17 18:18:04 +0000
+++ tests/unit/runtest.sh 2015-08-12 11:28:41 +0000
@@ -43,6 +43,8 @@
4343
44 if [ "$_MINIMAL" = "minimal" ]; then44 if [ "$_MINIMAL" = "minimal" ]; then
45 _CMD="$_CMD -p -platform -p minimal"45 _CMD="$_CMD -p -platform -p minimal"
46 elif [ "$_MINIMAL" = "custom" ]; then
47 _CMD="$_CMD -p -platform -p custom"
46 fi48 fi
4749
48 if [ $_TARGETPATH != $_TESTFILEPATH ]; then50 if [ $_TARGETPATH != $_TESTFILEPATH ]; then
4951
=== added directory 'tests/unit/tst_units/dpr1'
=== added file 'tests/unit/tst_units/dpr1/dpr1.pro'
--- tests/unit/tst_units/dpr1/dpr1.pro 1970-01-01 00:00:00 +0000
+++ tests/unit/tst_units/dpr1/dpr1.pro 2015-08-12 11:28:41 +0000
@@ -0,0 +1,3 @@
1include(../../test-include.pri)
2SOURCES += tst_units.cpp
3RESOURCES += dpr1.qrc
04
=== renamed file 'tests/unit/tst_units/tst_units.qrc' => 'tests/unit/tst_units/dpr1/dpr1.qrc'
=== renamed file 'tests/unit/tst_units/exact_match@8.png' => 'tests/unit/tst_units/dpr1/exact_match@8.png'
=== renamed file 'tests/unit/tst_units/exact_match_no_suffix.png' => 'tests/unit/tst_units/dpr1/exact_match_no_suffix.png'
=== renamed file 'tests/unit/tst_units/higher_scale.png' => 'tests/unit/tst_units/dpr1/higher_scale.png'
=== renamed file 'tests/unit/tst_units/lower_scale.png' => 'tests/unit/tst_units/dpr1/lower_scale.png'
=== renamed file 'tests/unit/tst_units/resource@1.png' => 'tests/unit/tst_units/dpr1/resource@1.png'
=== renamed file 'tests/unit/tst_units/resource@10.png' => 'tests/unit/tst_units/dpr1/resource@10.png'
=== renamed file 'tests/unit/tst_units/resource@15.png' => 'tests/unit/tst_units/dpr1/resource@15.png'
=== renamed file 'tests/unit/tst_units/resource@18.png' => 'tests/unit/tst_units/dpr1/resource@18.png'
=== renamed file 'tests/unit/tst_units/resource@19.png' => 'tests/unit/tst_units/dpr1/resource@19.png'
=== renamed file 'tests/unit/tst_units/resource@8.png' => 'tests/unit/tst_units/dpr1/resource@8.png'
=== renamed file 'tests/unit/tst_units/resource_only_higher@13.png' => 'tests/unit/tst_units/dpr1/resource_only_higher@13.png'
=== renamed file 'tests/unit/tst_units/resource_only_smaller@7.png' => 'tests/unit/tst_units/dpr1/resource_only_smaller@7.png'
=== renamed file 'tests/unit/tst_units/resources_unit' => 'tests/unit/tst_units/dpr1/resources_unit'
=== renamed file 'tests/unit/tst_units/tst_units.cpp' => 'tests/unit/tst_units/dpr1/tst_units.cpp'
=== added directory 'tests/unit/tst_units/dpr2'
=== added file 'tests/unit/tst_units/dpr2/dpr2.pro'
--- tests/unit/tst_units/dpr2/dpr2.pro 1970-01-01 00:00:00 +0000
+++ tests/unit/tst_units/dpr2/dpr2.pro 2015-08-12 11:28:41 +0000
@@ -0,0 +1,3 @@
1CONFIG += custom_qpa # needed by test to set device pixel ratio correctly
2include(../../test-include.pri)
3SOURCES += tst_units_dpr2.cpp
04
=== added file 'tests/unit/tst_units/dpr2/tst_units_dpr2.cpp'
--- tests/unit/tst_units/dpr2/tst_units_dpr2.cpp 1970-01-01 00:00:00 +0000
+++ tests/unit/tst_units/dpr2/tst_units_dpr2.cpp 2015-08-12 11:28:41 +0000
@@ -0,0 +1,143 @@
1/*
2 * Copyright (C) 2015 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <QtTest/QtTest>
18#include "ucunits.h"
19
20class tst_UCUnitsDPR2: public QObject
21{
22 Q_OBJECT
23
24private Q_SLOTS:
25
26 void dpGridUnitDefaultWithDPR2() {
27 UCUnits units;
28
29 QCOMPARE(units.dp(1.0), 1.0f);
30 QCOMPARE(units.dp(1.32), 1.5f);
31 QCOMPARE(units.dp(1.72), 1.5f);
32 QCOMPARE(units.dp(0.23), 0.0f);
33 QCOMPARE(units.dp(0.51), 0.5f);
34 QCOMPARE(units.dp(0.9999), 1.0f);
35 QCOMPARE(units.dp(1000.01), 1000.0f);
36 }
37
38 void guGridUnitDefaultWithDPR2() {
39 UCUnits units;
40
41 QCOMPARE(units.gu(0.5), 4.0f);
42 QCOMPARE(units.gu(1), 8.0f);
43 QCOMPARE(units.gu(1.5), 12.0f);
44 QCOMPARE(units.gu(2), 16.0f);
45 QCOMPARE(units.gu(4), 32.0f);
46 QCOMPARE(units.gu(100000), 800000.0f);
47 QCOMPARE(units.gu(150.51983), 1204.0f);
48 }
49
50 void dpGridUnitEightWithDPR2() {
51 UCUnits units;
52 units.setGridUnit(8);
53
54 QCOMPARE(units.dp(1.0), 0.5f);
55 QCOMPARE(units.dp(1.32), 0.5f);
56 QCOMPARE(units.dp(1.72), 1.0f);
57 QCOMPARE(units.dp(0.23), 0.0f);
58 QCOMPARE(units.dp(0.51), 0.5f);
59 QCOMPARE(units.dp(0.9999), 0.5f);
60 QCOMPARE(units.dp(1000.01), 500.0f);
61 }
62
63 void guGridUnitEightWithDPR2() {
64 UCUnits units;
65 units.setGridUnit(8);
66
67 QCOMPARE(units.gu(0.5), 2.0f);
68 QCOMPARE(units.gu(1), 4.0f);
69 QCOMPARE(units.gu(1.5), 6.0f);
70 QCOMPARE(units.gu(2), 8.0f);
71 QCOMPARE(units.gu(4), 16.0f);
72 QCOMPARE(units.gu(100000), 400000.0f);
73 QCOMPARE(units.gu(150.51983), 602.0f);
74 }
75
76 void dpGridUnitSixteenWithDPR2() {
77 UCUnits units;
78 units.setGridUnit(16);
79 /* This testcase covers unit calculations when the Qt device pixel ratio is 2.
80 *
81 */
82
83 QCOMPARE(units.dp(1.0), 1.0f);
84 QCOMPARE(units.dp(1.32), 1.5f);
85 QCOMPARE(units.dp(1.72), 1.5f);
86 QCOMPARE(units.dp(0.23), 0.0f);
87 QCOMPARE(units.dp(0.51), 0.5f);
88 QCOMPARE(units.dp(0.9999), 1.0f);
89 QCOMPARE(units.dp(1000.01), 1000.0f);
90 }
91
92 void guGridUnitSixteenWithDPR2() {
93 UCUnits units;
94 units.setGridUnit(16);
95
96 QCOMPARE(units.gu(0.5), 4.0f);
97 QCOMPARE(units.gu(1), 8.0f);
98 QCOMPARE(units.gu(1.5), 12.0f);
99 QCOMPARE(units.gu(2), 16.0f);
100 QCOMPARE(units.gu(4), 32.0f);
101 QCOMPARE(units.gu(100000), 800000.0f);
102 QCOMPARE(units.gu(150.51983), 1204.0f);
103 }
104
105 void dpGridUnitTwentyWithDPR2() {
106 UCUnits units;
107 units.setGridUnit(20);
108
109 QCOMPARE(units.dp(1.0), 1.0f);
110 QCOMPARE(units.dp(1.32), 1.5f);
111 QCOMPARE(units.dp(1.72), 1.5f);
112 QCOMPARE(units.dp(0.23), 0.0f);
113 QCOMPARE(units.dp(0.51), 0.5f);
114 QCOMPARE(units.dp(0.9999), 1.0f);
115 QCOMPARE(units.dp(1000.01), 1250.0f);
116 }
117
118 void guGridUnitTenWithDPR2() {
119 UCUnits units;
120 units.setGridUnit(10);
121
122 QCOMPARE(units.gu(0.5), 2.5f);
123 QCOMPARE(units.gu(1), 5.0f);
124 QCOMPARE(units.gu(1.5), 7.5f);
125 QCOMPARE(units.gu(2), 10.0f);
126 QCOMPARE(units.gu(4), 20.0f);
127 QCOMPARE(units.gu(100000), 500000.0f);
128 QCOMPARE(units.gu(150.51983), 752.5f);
129 }
130};
131
132//QTEST_MAIN(tst_UCUnitsDPR2) - want to set custom env var, so need to use actual code:
133int main(int argc, char *argv[])
134{
135 qputenv("QT_DEVICE_PIXEL_RATIO", "2");
136
137 QGuiApplication app(argc, argv);
138 app.setAttribute(Qt::AA_Use96Dpi, true);
139 tst_UCUnitsDPR2 tc;
140 return QTest::qExec(&tc, argc, argv);
141}
142
143#include "tst_units_dpr2.moc"
0144
=== added directory 'tests/unit/tst_units/dpr3'
=== added file 'tests/unit/tst_units/dpr3/dpr3.pro'
--- tests/unit/tst_units/dpr3/dpr3.pro 1970-01-01 00:00:00 +0000
+++ tests/unit/tst_units/dpr3/dpr3.pro 2015-08-12 11:28:41 +0000
@@ -0,0 +1,3 @@
1CONFIG += custom_qpa # needed by test to set device pixel ratio correctly
2include(../../test-include.pri)
3SOURCES += tst_units_dpr3.cpp
04
=== added file 'tests/unit/tst_units/dpr3/tst_units_dpr3.cpp'
--- tests/unit/tst_units/dpr3/tst_units_dpr3.cpp 1970-01-01 00:00:00 +0000
+++ tests/unit/tst_units/dpr3/tst_units_dpr3.cpp 2015-08-12 11:28:41 +0000
@@ -0,0 +1,88 @@
1/*
2 * Copyright (C) 2015 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <QtTest/QtTest>
18#include "ucunits.h"
19
20class tst_UCUnitsDPR3: public QObject
21{
22 Q_OBJECT
23
24private Q_SLOTS:
25
26 void dpGridUnitDefaultWithDPR3() {
27 UCUnits units;
28
29 QCOMPARE(units.dp(1.0), 1.0f);
30 QCOMPARE(units.dp(1.32), 1.33333f);
31 QCOMPARE(units.dp(1.72), 1.66666f);
32 QCOMPARE(units.dp(0.23), 0.333333f);
33 QCOMPARE(units.dp(0.51), 0.666666f);
34 QCOMPARE(units.dp(0.9999), 1.0f);
35 QCOMPARE(units.dp(1000.01), 1000.0f);
36 }
37
38 void guGridUnitDefaultWithDPR3() {
39 UCUnits units;
40
41 QCOMPARE(units.gu(0.5), 4.0f);
42 QCOMPARE(units.gu(1), 8.0f);
43 QCOMPARE(units.gu(1.5), 12.0f);
44 QCOMPARE(units.gu(2), 16.0f);
45 QCOMPARE(units.gu(4), 32.0f);
46 QCOMPARE(units.gu(100000), 800000.0f);
47 QCOMPARE(units.gu(150.51983), 1204.0f);
48 }
49
50 void dpGridUnitSixteenWithDPR3() {
51 UCUnits units;
52 units.setGridUnit(16);
53
54 QCOMPARE(units.dp(1.0), 0.666666f);
55 QCOMPARE(units.dp(1.32), 1.0f);
56 QCOMPARE(units.dp(1.72), 1.0f);
57 QCOMPARE(units.dp(0.23), 0.0f);
58 QCOMPARE(units.dp(0.51), 0.333333f);
59 QCOMPARE(units.dp(0.9999), 0.666666f);
60 QCOMPARE(units.dp(1000.01), 666.666666f);
61 }
62
63 void guGridUnitSixteenWithDPR3() {
64 UCUnits units;
65 units.setGridUnit(16);
66
67 QCOMPARE(units.gu(0.5), 2.666666f);
68 QCOMPARE(units.gu(1), 5.333333f);
69 QCOMPARE(units.gu(1.5), 8.0f);
70 QCOMPARE(units.gu(2), 10.666666f);
71 QCOMPARE(units.gu(4), 21.333333f);
72 QCOMPARE(units.gu(100000), 533333.333333f);
73 QCOMPARE(units.gu(150.51983), 802.666666f);
74 }
75};
76
77//QTEST_MAIN(tst_UCUnitsDPR3) - want to set custom env var, so need to use actual code:
78int main(int argc, char *argv[])
79{
80 qputenv("QT_DEVICE_PIXEL_RATIO", "3");
81
82 QGuiApplication app(argc, argv);
83 app.setAttribute(Qt::AA_Use96Dpi, true);
84 tst_UCUnitsDPR3 tc;
85 return QTest::qExec(&tc, argc, argv);
86}
87
88#include "tst_units_dpr3.moc"
089
=== modified file 'tests/unit/tst_units/tst_units.pro'
--- tests/unit/tst_units/tst_units.pro 2012-10-09 17:54:43 +0000
+++ tests/unit/tst_units/tst_units.pro 2015-08-12 11:28:41 +0000
@@ -1,3 +1,6 @@
1include(../test-include.pri)1TEMPLATE = subdirs
2SOURCES += tst_units.cpp2
3RESOURCES += tst_units.qrc3SUBDIRS += \
4 dpr1 \
5 dpr2 \
6 dpr3
47
=== modified file 'tests/unit/unit.pro'
--- tests/unit/unit.pro 2015-03-10 11:49:27 +0000
+++ tests/unit/unit.pro 2015-08-12 11:28:41 +0000
@@ -14,7 +14,9 @@
14 tst_components_benchmark14 tst_components_benchmark
15#}15#}
1616
17SUBDIRS += tst_units \17SUBDIRS += \
18 custom_qpa \
19 tst_units \
18 tst_scaling_image_provider \20 tst_scaling_image_provider \
19 tst_qquick_image_extension \21 tst_qquick_image_extension \
20 tst_performance \22 tst_performance \

Subscribers

People subscribed via source and target branches