Merge remote-tracking branch 'gerrit/dev' into wip/cmake

Change-Id: I2e1812e4f40131ff74919aa3b558db5c261fe412
bb10
Tobias Hunger 2019-04-16 16:50:27 +02:00
commit bbb75d9614
19 changed files with 756 additions and 304 deletions

View File

@ -159,6 +159,9 @@ public abstract class QtLoader {
protected ComponentInfo m_contextInfo;
private Class<?> m_delegateClass;
private static ArrayList<FileOutputStream> m_fileOutputStreams = new ArrayList<FileOutputStream>();
// List of open file streams associated with files copied during installation.
QtLoader(ContextWrapper context, Class<?> clazz) {
m_context = context;
m_delegateClass = clazz;
@ -357,7 +360,7 @@ public abstract class QtLoader {
AssetManager assetsManager = m_context.getAssets();
InputStream inputStream = null;
OutputStream outputStream = null;
FileOutputStream outputStream = null;
try {
inputStream = assetsManager.open(source);
outputStream = new FileOutputStream(destinationFile);
@ -369,8 +372,12 @@ public abstract class QtLoader {
inputStream.close();
if (outputStream != null)
outputStream.close();
// Ensure that the buffered data is flushed to the OS for writing.
outputStream.flush();
}
// Mark the output stream as still needing to be written to physical disk.
// The output stream will be closed after this sync completes.
m_fileOutputStreams.add(outputStream);
}
private static void createBundledBinary(String source, String destination)
@ -388,7 +395,7 @@ public abstract class QtLoader {
destinationFile.createNewFile();
InputStream inputStream = null;
OutputStream outputStream = null;
FileOutputStream outputStream = null;
try {
inputStream = new FileInputStream(source);
outputStream = new FileOutputStream(destinationFile);
@ -400,8 +407,12 @@ public abstract class QtLoader {
inputStream.close();
if (outputStream != null)
outputStream.close();
// Ensure that the buffered data is flushed to the OS for writing.
outputStream.flush();
}
// Mark the output stream as still needing to be written to physical disk.
// The output stream will be closed after this sync completes.
m_fileOutputStreams.add(outputStream);
}
private boolean cleanCacheIfNecessary(String pluginsPrefix, long packageVersion)
@ -449,27 +460,6 @@ public abstract class QtLoader {
if (!cleanCacheIfNecessary(pluginsPrefix, packageVersion))
return;
{
File versionFile = new File(pluginsPrefix + "cache.version");
File parentDirectory = versionFile.getParentFile();
if (!parentDirectory.exists())
parentDirectory.mkdirs();
versionFile.createNewFile();
DataOutputStream outputStream = null;
try {
outputStream = new DataOutputStream(new FileOutputStream(versionFile));
outputStream.writeLong(packageVersion);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outputStream != null)
outputStream.close();
}
}
{
// why can't we load the plugins directly from libs ?!?!
String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY;
@ -499,6 +489,66 @@ public abstract class QtLoader {
}
}
// The Java compiler must be assured that variables belonging to this parent thread will not
// go out of scope during the runtime of the spawned thread (since in general spawned
// threads can outlive their parent threads). Copy variables and declare as 'final' before
// passing into the spawned thread.
final String pluginsPrefixFinal = pluginsPrefix;
final long packageVersionFinal = packageVersion;
// Spawn a worker thread to write all installed files to physical disk and indicate
// successful installation by creating the 'cache.version' file.
new Thread(new Runnable() {
@Override
public void run() {
try {
finalizeInstallation(pluginsPrefixFinal, packageVersionFinal);
} catch (Exception e) {
Log.e(QtApplication.QtTAG, e.getMessage());
e.printStackTrace();
return;
}
}
}).start();
}
private void finalizeInstallation(String pluginsPrefix, long packageVersion)
throws IOException
{
{
// Write all installed files to physical disk and close each output stream
for (FileOutputStream fileOutputStream : m_fileOutputStreams) {
fileOutputStream.getFD().sync();
fileOutputStream.close();
}
m_fileOutputStreams.clear();
}
{
// Create 'cache.version' file
File versionFile = new File(pluginsPrefix + "cache.version");
File parentDirectory = versionFile.getParentFile();
if (!parentDirectory.exists())
parentDirectory.mkdirs();
versionFile.createNewFile();
DataOutputStream outputStream = null;
try {
outputStream = new DataOutputStream(new FileOutputStream(versionFile));
outputStream.writeLong(packageVersion);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outputStream != null)
outputStream.close();
}
}
}
private void deleteRecursively(File directory)

View File

@ -60,7 +60,8 @@ enum class QtPluginMetaDataKeys {
Requirements,
IID,
ClassName,
MetaData
MetaData,
URI
};
// F(IntKey, StringKey, Description)
@ -68,7 +69,8 @@ enum class QtPluginMetaDataKeys {
#define QT_PLUGIN_FOREACH_METADATA(F) \
F(QtPluginMetaDataKeys::IID, "IID", "Plugin's Interface ID") \
F(QtPluginMetaDataKeys::ClassName, "className", "Plugin class name") \
F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data")
F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data") \
F(QtPluginMetaDataKeys::URI, "URI", "Plugin URI")
QT_END_NAMESPACE

View File

@ -476,7 +476,7 @@
"tslib": {
"label": "tslib",
"test": {
"main": "ts_open(\"foo\", 0);"
"main": "ts_setup(nullptr, 0);"
},
"headers": "tslib.h",
"sources": [

View File

@ -39,6 +39,7 @@
#include "qcolor.h"
#include "qcolor_p.h"
#include "qfloat16.h"
#include "qnamespace.h"
#include "qdatastream.h"
#include "qvariant.h"
@ -494,6 +495,14 @@ static QStringList get_colornames()
with this value, a pixel value will be used that is appropriate for the
underlying pixel format in use.
\section1 The Extended RGB Color Model
The extended RGB color model, also known as the scRGB color space,
is the same the RGB color model except it allows values under 0.0,
and over 1.0. This makes it possible to represent colors that would
otherwise be outside the range of the RGB colorspace but still use
the same values for colors inside the RGB colorspace.
\section1 The HSV Color Model
The RGB model is hardware-oriented. Its representation is close to
@ -603,12 +612,13 @@ static QStringList get_colornames()
/*!
\enum QColor::Spec
The type of color specified, either RGB, HSV, CMYK or HSL.
The type of color specified, either RGB, extended RGB, HSV, CMYK or HSL.
\value Rgb
\value Hsv
\value Cmyk
\value Hsl
\value ExtendedRgb
\value Invalid
\sa spec(), convertTo()
@ -778,6 +788,10 @@ QColor::QColor(Spec spec) noexcept
case Hsl:
setHsl(0, 0, 0, 0);
break;
case ExtendedRgb:
cspec = spec;
setRgbF(0, 0, 0, 0);
break;
}
}
@ -1211,6 +1225,17 @@ void QColor::setHsl(int h, int s, int l, int a)
ct.ahsl.pad = 0;
}
static inline qfloat16 &castF16(quint16 &v)
{
// this works because qfloat16 internally is a quint16
return *reinterpret_cast<qfloat16 *>(&v);
}
static inline const qfloat16 &castF16(const quint16 &v)
{
return *reinterpret_cast<const qfloat16 *>(&v);
}
/*!
Sets the contents pointed to by \a r, \a g, \a b, and \a a, to the red,
green, blue, and alpha-channel (transparency) components of the color's
@ -1226,18 +1251,27 @@ void QColor::getRgbF(qreal *r, qreal *g, qreal *b, qreal *a) const
if (!r || !g || !b)
return;
if (cspec != Invalid && cspec != Rgb) {
if (cspec == Invalid)
return;
if (cspec != Rgb && cspec != ExtendedRgb) {
toRgb().getRgbF(r, g, b, a);
return;
}
*r = ct.argb.red / qreal(USHRT_MAX);
*g = ct.argb.green / qreal(USHRT_MAX);
*b = ct.argb.blue / qreal(USHRT_MAX);
if (a)
*a = ct.argb.alpha / qreal(USHRT_MAX);
if (cspec == Rgb) {
*r = ct.argb.red / qreal(USHRT_MAX);
*g = ct.argb.green / qreal(USHRT_MAX);
*b = ct.argb.blue / qreal(USHRT_MAX);
if (a)
*a = ct.argb.alpha / qreal(USHRT_MAX);
} else {
*r = castF16(ct.argbExtended.redF16);
*g = castF16(ct.argbExtended.greenF16);
*b = castF16(ct.argbExtended.blueF16);
if (a)
*a = castF16(ct.argbExtended.alphaF16);
}
}
/*!
@ -1274,26 +1308,35 @@ void QColor::getRgb(int *r, int *g, int *b, int *a) const
Sets the color channels of this color to \a r (red), \a g (green),
\a b (blue) and \a a (alpha, transparency).
All values must be in the range 0.0-1.0.
The alpha value must be in the range 0.0-1.0.
If any of the other values are outside the range of 0.0-1.0 the
color model will be set as \c ExtendedRgb.
\sa rgb(), getRgbF(), setRgb()
*/
void QColor::setRgbF(qreal r, qreal g, qreal b, qreal a)
{
if (r < qreal(0.0) || r > qreal(1.0)
|| g < qreal(0.0) || g > qreal(1.0)
|| b < qreal(0.0) || b > qreal(1.0)
|| a < qreal(0.0) || a > qreal(1.0)) {
qWarning("QColor::setRgbF: RGB parameters out of range");
if (a < qreal(0.0) || a > qreal(1.0)) {
qWarning("QColor::setRgbF: Alpha parameter is out of range");
invalidate();
return;
}
if (r < qreal(0.0) || r > qreal(1.0) ||
g < qreal(0.0) || g > qreal(1.0) ||
b < qreal(0.0) || b > qreal(1.0) || cspec == ExtendedRgb) {
cspec = ExtendedRgb;
castF16(ct.argbExtended.redF16) = qfloat16(r);
castF16(ct.argbExtended.greenF16) = qfloat16(g);
castF16(ct.argbExtended.blueF16) = qfloat16(b);
castF16(ct.argbExtended.alphaF16) = qfloat16(a);
ct.argbExtended.pad = 0;
return;
}
cspec = Rgb;
ct.argb.alpha = qRound(a * USHRT_MAX);
ct.argb.red = qRound(r * USHRT_MAX);
ct.argb.green = qRound(g * USHRT_MAX);
ct.argb.blue = qRound(b * USHRT_MAX);
ct.argb.alpha = qRound(a * USHRT_MAX);
ct.argb.pad = 0;
}
@ -1421,7 +1464,11 @@ void QColor::setRgb(QRgb rgb) noexcept
\sa setAlpha(), alphaF(), {QColor#Alpha-Blended Drawing}{Alpha-Blended Drawing}
*/
int QColor::alpha() const noexcept
{ return ct.argb.alpha >> 8; }
{
if (cspec == ExtendedRgb)
return qRound(qreal(castF16(ct.argbExtended.alphaF16)) * 255);
return ct.argb.alpha >> 8;
}
/*!
@ -1434,6 +1481,11 @@ int QColor::alpha() const noexcept
void QColor::setAlpha(int alpha)
{
QCOLOR_INT_RANGE_CHECK("QColor::setAlpha", alpha);
if (cspec == ExtendedRgb) {
constexpr qreal f = qreal(1.0) / 255;
castF16(ct.argbExtended.alphaF16) = alpha * f;
return;
}
ct.argb.alpha = alpha * 0x101;
}
@ -1443,7 +1495,11 @@ void QColor::setAlpha(int alpha)
\sa setAlphaF(), alpha(), {QColor#Alpha-Blended Drawing}{Alpha-Blended Drawing}
*/
qreal QColor::alphaF() const noexcept
{ return ct.argb.alpha / qreal(USHRT_MAX); }
{
if (cspec == ExtendedRgb)
return castF16(ct.argbExtended.alphaF16);
return ct.argb.alpha / qreal(USHRT_MAX);
}
/*!
Sets the alpha of this color to \a alpha. qreal alpha is specified in the
@ -1455,6 +1511,10 @@ qreal QColor::alphaF() const noexcept
void QColor::setAlphaF(qreal alpha)
{
QCOLOR_REAL_RANGE_CHECK("QColor::setAlphaF", alpha);
if (cspec == ExtendedRgb) {
castF16(ct.argbExtended.alphaF16) = alpha;
return;
}
qreal tmp = alpha * USHRT_MAX;
ct.argb.alpha = qRound(tmp);
}
@ -1550,25 +1610,29 @@ void QColor::setBlue(int blue)
*/
qreal QColor::redF() const noexcept
{
if (cspec != Invalid && cspec != Rgb)
return toRgb().redF();
return ct.argb.red / qreal(USHRT_MAX);
if (cspec == Rgb || cspec == Invalid)
return ct.argb.red / qreal(USHRT_MAX);
if (cspec == ExtendedRgb)
return castF16(ct.argbExtended.redF16);
return toRgb().redF();
}
/*!
Sets the red color component of this color to \a red. Float components
are specified in the range 0.0-1.0.
Sets the red color component of this color to \a red. If \a red lies outside
the 0.0-1.0 range, the color model will be changed to \c ExtendedRgb.
\sa redF(), red(), setRgbF()
*/
void QColor::setRedF(qreal red)
{
QCOLOR_REAL_RANGE_CHECK("QColor::setRedF", red);
if (cspec != Rgb)
setRgbF(red, greenF(), blueF(), alphaF());
else
if (cspec == Rgb && red >= qreal(0.0) && red <= qreal(1.0))
ct.argb.red = qRound(red * USHRT_MAX);
else if (cspec == ExtendedRgb)
castF16(ct.argbExtended.redF16) = red;
else
setRgbF(red, greenF(), blueF(), alphaF());
}
/*!
@ -1578,25 +1642,29 @@ void QColor::setRedF(qreal red)
*/
qreal QColor::greenF() const noexcept
{
if (cspec != Invalid && cspec != Rgb)
return toRgb().greenF();
return ct.argb.green / qreal(USHRT_MAX);
if (cspec == Rgb || cspec == Invalid)
return ct.argb.green / qreal(USHRT_MAX);
if (cspec == ExtendedRgb)
return castF16(ct.argbExtended.greenF16);
return toRgb().greenF();
}
/*!
Sets the green color component of this color to \a green. Float components
are specified in the range 0.0-1.0.
Sets the green color component of this color to \a green. If \a green lies outside
the 0.0-1.0 range, the color model will be changed to \c ExtendedRgb.
\sa greenF(), green(), setRgbF()
*/
void QColor::setGreenF(qreal green)
{
QCOLOR_REAL_RANGE_CHECK("QColor::setGreenF", green);
if (cspec != Rgb)
setRgbF(redF(), green, blueF(), alphaF());
else
if (cspec == Rgb && green >= qreal(0.0) && green <= qreal(1.0))
ct.argb.green = qRound(green * USHRT_MAX);
else if (cspec == ExtendedRgb)
castF16(ct.argbExtended.greenF16) = green;
else
setRgbF(redF(), green, blueF(), alphaF());
}
/*!
@ -1606,24 +1674,27 @@ void QColor::setGreenF(qreal green)
*/
qreal QColor::blueF() const noexcept
{
if (cspec != Invalid && cspec != Rgb)
return toRgb().blueF();
return ct.argb.blue / qreal(USHRT_MAX);
if (cspec == Rgb || cspec == Invalid)
return ct.argb.blue / qreal(USHRT_MAX);
if (cspec == ExtendedRgb)
return castF16(ct.argbExtended.blueF16);
return toRgb().blueF();
}
/*!
Sets the blue color component of this color to \a blue. Float components
are specified in the range 0.0-1.0.
Sets the blue color component of this color to \a blue. If \a blue lies outside
the 0.0-1.0 range, the color model will be changed to \c ExtendedRgb.
\sa blueF(), blue(), setRgbF()
*/
void QColor::setBlueF(qreal blue)
{
QCOLOR_REAL_RANGE_CHECK("QColor::setBlueF", blue);
if (cspec != Rgb)
setRgbF(redF(), greenF(), blue, alphaF());
else
if (cspec == Rgb && blue >= qreal(0.0) && blue <= qreal(1.0))
ct.argb.blue = qRound(blue * USHRT_MAX);
else if (cspec == ExtendedRgb)
castF16(ct.argbExtended.blueF16) = blue;
else
setRgbF(redF(), greenF(), blue, alphaF());
}
/*!
@ -1932,6 +2003,30 @@ qreal QColor::blackF() const noexcept
return ct.acmyk.black / qreal(USHRT_MAX);
}
/*!
Create and returns an extended RGB QColor based on this color.
\since 5.14
\sa toRgb, convertTo()
*/
QColor QColor::toExtendedRgb() const noexcept
{
if (!isValid() || cspec == ExtendedRgb)
return *this;
if (cspec != Rgb)
return toRgb().toExtendedRgb();
constexpr qreal f = qreal(1.0) / USHRT_MAX;
QColor color;
color.cspec = ExtendedRgb;
castF16(color.ct.argbExtended.alphaF16) = qfloat16(ct.argb.alpha * f);
castF16(color.ct.argbExtended.redF16) = qfloat16(ct.argb.red * f);
castF16(color.ct.argbExtended.greenF16) = qfloat16(ct.argb.green * f);
castF16(color.ct.argbExtended.blueF16) = qfloat16(ct.argb.blue * f);
color.ct.argbExtended.pad = 0;
return color;
}
/*!
Create and returns an RGB QColor based on this color.
@ -1944,7 +2039,8 @@ QColor QColor::toRgb() const noexcept
QColor color;
color.cspec = Rgb;
color.ct.argb.alpha = ct.argb.alpha;
if (cspec != ExtendedRgb)
color.ct.argb.alpha = ct.argb.alpha;
color.ct.argb.pad = 0;
switch (cspec) {
@ -2066,6 +2162,12 @@ QColor QColor::toRgb() const noexcept
color.ct.argb.blue = qRound((qreal(1.0) - (y * (qreal(1.0) - k) + k)) * USHRT_MAX);
break;
}
case ExtendedRgb:
color.ct.argb.alpha = qRound(USHRT_MAX * qreal(castF16(ct.argbExtended.alphaF16)));
color.ct.argb.red = qRound(USHRT_MAX * qBound(qreal(0.0), qreal(castF16(ct.argbExtended.redF16)), qreal(1.0)));
color.ct.argb.green = qRound(USHRT_MAX * qBound(qreal(0.0), qreal(castF16(ct.argbExtended.greenF16)), qreal(1.0)));
color.ct.argb.blue = qRound(USHRT_MAX * qBound(qreal(0.0), qreal(castF16(ct.argbExtended.blueF16)), qreal(1.0)));
break;
default:
break;
}
@ -2238,6 +2340,8 @@ QColor QColor::convertTo(QColor::Spec colorSpec) const noexcept
switch (colorSpec) {
case Rgb:
return toRgb();
case ExtendedRgb:
return toExtendedRgb();
case Hsv:
return toHsv();
case Cmyk:
@ -2317,20 +2421,32 @@ QColor QColor::fromRgb(int r, int g, int b, int a)
color values, \a r (red), \a g (green), \a b (blue), and \a a
(alpha-channel, i.e. transparency).
All the values must be in the range 0.0-1.0.
The alpha value must be in the range 0.0-1.0.
If any of the other values are outside the range of 0.0-1.0 the
color model will be set as \c ExtendedRgb.
\sa fromRgb(), fromRgba64(), toRgb(), isValid()
*/
QColor QColor::fromRgbF(qreal r, qreal g, qreal b, qreal a)
{
if (r < qreal(0.0) || r > qreal(1.0)
|| g < qreal(0.0) || g > qreal(1.0)
|| b < qreal(0.0) || b > qreal(1.0)
|| a < qreal(0.0) || a > qreal(1.0)) {
qWarning("QColor::fromRgbF: RGB parameters out of range");
if (a < qreal(0.0) || a > qreal(1.0)) {
qWarning("QColor::fromRgbF: Alpha parameter out of range");
return QColor();
}
if (r < qreal(0.0) || r > qreal(1.0)
|| g < qreal(0.0) || g > qreal(1.0)
|| b < qreal(0.0) || b > qreal(1.0)) {
QColor color;
color.cspec = ExtendedRgb;
castF16(color.ct.argbExtended.alphaF16) = qfloat16(a);
castF16(color.ct.argbExtended.redF16) = qfloat16(r);
castF16(color.ct.argbExtended.greenF16) = qfloat16(g);
castF16(color.ct.argbExtended.blueF16) = qfloat16(b);
color.ct.argbExtended.pad = 0;
return color;
}
QColor color;
color.cspec = Rgb;
color.ct.argb.alpha = qRound(a * USHRT_MAX);
@ -2885,6 +3001,8 @@ QDebug operator<<(QDebug dbg, const QColor &c)
dbg.nospace() << "QColor(Invalid)";
else if (c.spec() == QColor::Rgb)
dbg.nospace() << "QColor(ARGB " << c.alphaF() << ", " << c.redF() << ", " << c.greenF() << ", " << c.blueF() << ')';
else if (c.spec() == QColor::ExtendedRgb)
dbg.nospace() << "QColor(Ext. ARGB " << c.alphaF() << ", " << c.redF() << ", " << c.greenF() << ", " << c.blueF() << ')';
else if (c.spec() == QColor::Hsv)
dbg.nospace() << "QColor(AHSV " << c.alphaF() << ", " << c.hueF() << ", " << c.saturationF() << ", " << c.valueF() << ')';
else if (c.spec() == QColor::Cmyk)

View File

@ -64,7 +64,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QColor &);
class Q_GUI_EXPORT QColor
{
public:
enum Spec { Invalid, Rgb, Hsv, Cmyk, Hsl };
enum Spec { Invalid, Rgb, Hsv, Cmyk, Hsl, ExtendedRgb };
enum NameFormat { HexRgb, HexArgb };
inline QColor() noexcept;
@ -198,6 +198,7 @@ public:
QColor toHsv() const noexcept;
QColor toCmyk() const noexcept;
QColor toHsl() const noexcept;
QColor toExtendedRgb() const noexcept;
Q_REQUIRED_RESULT QColor convertTo(Spec colorSpec) const noexcept;
@ -275,6 +276,13 @@ private:
ushort lightness;
ushort pad;
} ahsl;
struct {
ushort alphaF16;
ushort redF16;
ushort greenF16;
ushort blueF16;
ushort pad;
} argbExtended;
ushort array[5];
} ct;

View File

@ -204,19 +204,36 @@ QColor QColorTransform::map(const QColor &color) const
if (!d_ptr)
return color;
Q_D(const QColorTransform);
QColorVector c = { (float)color.redF(), (float)color.greenF(), (float)color.blueF() };
c.x = d->colorSpaceIn->trc[0].apply(c.x);
c.y = d->colorSpaceIn->trc[1].apply(c.y);
c.z = d->colorSpaceIn->trc[2].apply(c.z);
c = d->colorMatrix.map(c);
if (d_ptr->colorSpaceOut->lutsGenerated.loadAcquire()) {
c.x = d->colorSpaceOut->lut[0]->fromLinear(c.x);
c.y = d->colorSpaceOut->lut[1]->fromLinear(c.y);
c.z = d->colorSpaceOut->lut[2]->fromLinear(c.z);
QColor clr = color;
if (color.spec() != QColor::ExtendedRgb || color.spec() != QColor::Rgb)
clr = clr.toRgb();
QColorVector c = { (float)clr.redF(), (float)clr.greenF(), (float)clr.blueF() };
if (clr.spec() == QColor::ExtendedRgb) {
c.x = d->colorSpaceIn->trc[0].applyExtended(c.x);
c.y = d->colorSpaceIn->trc[1].applyExtended(c.y);
c.z = d->colorSpaceIn->trc[2].applyExtended(c.z);
} else {
c.x = d->colorSpaceOut->trc[0].applyInverse(c.x);
c.y = d->colorSpaceOut->trc[1].applyInverse(c.y);
c.z = d->colorSpaceOut->trc[2].applyInverse(c.z);
c.x = d->colorSpaceIn->trc[0].apply(c.x);
c.y = d->colorSpaceIn->trc[1].apply(c.y);
c.z = d->colorSpaceIn->trc[2].apply(c.z);
}
c = d->colorMatrix.map(c);
bool inGamut = c.x >= 0.0f && c.x <= 1.0f && c.y >= 0.0f && c.y <= 1.0f && c.z >= 0.0f && c.z <= 1.0f;
if (inGamut) {
if (d_ptr->colorSpaceOut->lutsGenerated.loadAcquire()) {
c.x = d->colorSpaceOut->lut[0]->fromLinear(c.x);
c.y = d->colorSpaceOut->lut[1]->fromLinear(c.y);
c.z = d->colorSpaceOut->lut[2]->fromLinear(c.z);
} else {
c.x = d->colorSpaceOut->trc[0].applyInverse(c.x);
c.y = d->colorSpaceOut->trc[1].applyInverse(c.y);
c.z = d->colorSpaceOut->trc[2].applyInverse(c.z);
}
} else {
c.x = d->colorSpaceOut->trc[0].applyInverseExtended(c.x);
c.y = d->colorSpaceOut->trc[1].applyInverseExtended(c.y);
c.z = d->colorSpaceOut->trc[2].applyInverseExtended(c.z);
}
QColor out;
out.setRgbF(c.x, c.y, c.z, color.alphaF());

View File

@ -91,7 +91,16 @@ public:
return m_fun.apply(x);
return x;
}
float applyExtended(float x) const
{
if (x >= 0.0f && x <= 1.0f)
return apply(x);
if (m_type == Type::Function)
return std::copysign(m_fun.apply(std::abs(x)), x);
if (m_type == Type::Table)
return x < 0.0f ? 0.0f : 1.0f;
return x;
}
float applyInverse(float x) const
{
if (m_type == Type::Table)
@ -100,6 +109,16 @@ public:
return m_fun.inverted().apply(x);
return x;
}
float applyInverseExtended(float x) const
{
if (x >= 0.0f && x <= 1.0f)
return applyInverse(x);
if (m_type == Type::Function)
return std::copysign(applyInverse(x), x);
if (m_type == Type::Table)
return x < 0.0f ? 0.0f : 1.0f;
return x;
}
friend inline bool operator!=(const QColorTrc &o1, const QColorTrc &o2);
friend inline bool operator==(const QColorTrc &o1, const QColorTrc &o2);

View File

@ -62,31 +62,15 @@ QTsLibMouseHandler::QTsLibMouseHandler(const QString &key,
qCDebug(qLcTsLib) << "Initializing tslib plugin" << key << specification;
setObjectName(QLatin1String("TSLib Mouse Handler"));
QByteArray device = qgetenv("TSLIB_TSDEVICE");
if (specification.startsWith(QLatin1String("/dev/")))
device = specification.toLocal8Bit();
if (device.isEmpty())
device = QByteArrayLiteral("/dev/input/event1");
m_dev = ts_open(device.constData(), 1);
m_dev = ts_setup(nullptr, 1);
if (!m_dev) {
qErrnoWarning(errno, "ts_open() failed");
qErrnoWarning(errno, "ts_setup() failed");
return;
}
if (ts_config(m_dev))
qErrnoWarning(errno, "ts_config() failed");
int fd = ts_fd(m_dev);
if (fd >= 0) {
qCDebug(qLcTsLib) << "tslib device is" << device;
m_notify = new QSocketNotifier(fd, QSocketNotifier::Read, this);
connect(m_notify, &QSocketNotifier::activated, this, &QTsLibMouseHandler::readMouseData);
} else {
qErrnoWarning(errno, "tslib: Cannot open input device %s", device.constData());
}
qCDebug(qLcTsLib) << "tslib device is" << ts_get_eventpath(m_dev);
m_notify = new QSocketNotifier(ts_fd(m_dev), QSocketNotifier::Read, this);
connect(m_notify, &QSocketNotifier::activated, this, &QTsLibMouseHandler::readMouseData);
}
QTsLibMouseHandler::~QTsLibMouseHandler()

View File

@ -65,6 +65,9 @@ public:
void setParent(const QPlatformWindow *window) override;
WId winId() const override { return m_windowId; }
bool setMouseGrabEnabled(bool grab) override { return false; }
bool setKeyboardGrabEnabled(bool grab) override { return false; }
QAndroidPlatformScreen *platformScreen() const;
void propagateSizeHints() override;

View File

@ -1652,6 +1652,12 @@ void Generator::generatePluginMetaData()
jsonObjectToCbor(&map, o);
}
if (!cdef->pluginData.uri.isEmpty()) {
dev.nextItem("\"URI\"");
cbor_encode_int(&map, int(QtPluginMetaDataKeys::URI));
cbor_encode_text_string(&map, cdef->pluginData.uri.constData(), cdef->pluginData.uri.size());
}
// Add -M args from the command line:
for (auto it = cdef->pluginData.metaArgs.cbegin(), end = cdef->pluginData.metaArgs.cend(); it != end; ++it) {
const QJsonArray &a = it.value();

View File

@ -1311,6 +1311,9 @@ void Moc::parsePluginData(ClassDef *def)
if (l == "IID") {
next(STRING_LITERAL);
def->pluginData.iid = unquotedLexem();
} else if (l == "URI") {
next(STRING_LITERAL);
def->pluginData.uri = unquotedLexem();
} else if (l == "FILE") {
next(STRING_LITERAL);
QByteArray metaDataFile = unquotedLexem();
@ -1351,6 +1354,7 @@ void Moc::parsePluginData(ClassDef *def)
+ " does not contain a valid JSON object. Declaration will be ignored";
warning(msg.constData());
def->pluginData.iid = QByteArray();
def->pluginData.uri = QByteArray();
return;
}
}

View File

@ -167,6 +167,7 @@ struct ClassDef : BaseDef {
struct PluginData {
QByteArray iid;
QByteArray uri;
QMap<QString, QJsonArray> metaArgs;
QJsonDocument metaData;
} pluginData;

View File

@ -556,7 +556,7 @@ void WriteInitialization::acceptUI(DomUI *node)
m_output << m_option.indent << language::endFunctionDefinition("setupUi");
if (!m_mainFormUsedInRetranslateUi) {
if (!m_mainFormUsedInRetranslateUi && language::language() == Language::Cpp) {
m_refreshInitialization += m_indent;
m_refreshInitialization += QLatin1String("Q_UNUSED(");
m_refreshInitialization += varName ;
@ -1760,55 +1760,76 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
// check cache
const IconHandle iconHandle(i);
const IconPropertiesNameMap::const_iterator it = m_iconPropertiesNameMap.constFind(iconHandle);
if (it != m_iconPropertiesNameMap.constEnd()) {
if (it != m_iconPropertiesNameMap.constEnd())
return it.value();
}
// insert with new name
const QString iconName = m_driver->unique(QLatin1String("icon"));
m_iconPropertiesNameMap.insert(IconHandle(i), iconName);
if (isIconFormat44(i)) {
if (i->attributeTheme().isEmpty()) {
// No theme: Write resource icon as is
m_output << m_indent << "QIcon " << iconName << ";\n";
if (m_uic->pixmapFunction().isEmpty())
writeResourceIcon(m_output, iconName, m_indent, i);
else
writePixmapFunctionIcon(m_output, iconName, m_indent, i);
} else {
// Theme: Generate code to check the theme and default to resource
if (iconHasStatePixmaps(i)) {
// Theme + default state pixmaps:
// Generate code to check the theme and default to state pixmaps
m_output << m_indent << "QIcon " << iconName << ";\n";
const char themeNameStringVariableC[] = "iconThemeName";
// Store theme name in a variable
m_output << m_indent;
if (m_firstThemeIcon) { // Declare variable string
m_output << "QString ";
m_firstThemeIcon = false;
}
m_output << themeNameStringVariableC << " = "
<< language::qstring(i->attributeTheme()) << ";\n";
m_output << m_indent << "if (QIcon::hasThemeIcon("
<< themeNameStringVariableC
<< ")) {\n"
<< m_dindent << iconName << " = QIcon::fromTheme(" << themeNameStringVariableC << ");\n"
<< m_indent << "} else {\n";
if (m_uic->pixmapFunction().isEmpty())
writeResourceIcon(m_output, iconName, m_dindent, i);
else
writePixmapFunctionIcon(m_output, iconName, m_dindent, i);
m_output << m_indent << "}\n";
} else {
// Theme, but no state pixmaps: Construct from theme directly.
m_output << m_indent << "QIcon " << iconName << "(QIcon::fromTheme("
<< language::qstring(i->attributeTheme()) << "));\n";
} // Theme, but not state
} // >= 4.4
} else { // pre-4.4 legacy
m_output << m_indent << "const QIcon " << iconName << " = " << pixCall(QLatin1String("QIcon"), i->text())<< ";\n";
const bool isCpp = language::language() == Language::Cpp;
if (Q_UNLIKELY(!isIconFormat44(i))) { // pre-4.4 legacy
m_output << m_indent;
if (isCpp)
m_output << "const QIcon ";
m_output << iconName << " = " << pixCall(QLatin1String("QIcon"), i->text())
<< language::eol;
return iconName;
}
// 4.4 onwards
if (i->attributeTheme().isEmpty()) {
// No theme: Write resource icon as is
m_output << m_indent << language::stackVariable("QIcon", iconName)
<< language::eol;
if (m_uic->pixmapFunction().isEmpty())
writeResourceIcon(m_output, iconName, m_indent, i);
else
writePixmapFunctionIcon(m_output, iconName, m_indent, i);
return iconName;
}
// Theme: Generate code to check the theme and default to resource
if (iconHasStatePixmaps(i)) {
// Theme + default state pixmaps:
// Generate code to check the theme and default to state pixmaps
m_output << m_indent << language::stackVariable("QIcon", iconName) << ";\n";
const char themeNameStringVariableC[] = "iconThemeName";
// Store theme name in a variable
m_output << m_indent;
if (m_firstThemeIcon) { // Declare variable string
if (isCpp)
m_output << "QString ";
m_firstThemeIcon = false;
}
m_output << themeNameStringVariableC << " = "
<< language::qstring(i->attributeTheme()) << language::eol;
m_output << m_indent << "if ";
if (isCpp)
m_output << '(';
m_output << "QIcon" << language::qualifier << "hasThemeIcon("
<< themeNameStringVariableC << ')' << (isCpp ? ") {" : ":") << '\n'
<< m_dindent << iconName << " = QIcon" << language::qualifier << "fromTheme("
<< themeNameStringVariableC << ')' << language::eol
<< m_indent << (isCpp ? "} else {" : "else:") << '\n';
if (m_uic->pixmapFunction().isEmpty())
writeResourceIcon(m_output, iconName, m_dindent, i);
else
writePixmapFunctionIcon(m_output, iconName, m_dindent, i);
m_output << m_indent;
if (isCpp)
m_output << '}';
m_output << '\n';
return iconName;
}
// Theme, but no state pixmaps: Construct from theme directly.
m_output << m_indent
<< language::stackVariableWithInitParameters("QIcon", iconName)
<< "QIcon" << language::qualifier << "fromTheme("
<< language::qstring(i->attributeTheme()) << "))"
<< language::eol;
return iconName;
}
@ -1910,31 +1931,36 @@ void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brush
const QString gradientType = gradient->attributeType();
const QString gradientName = m_driver->unique(QLatin1String("gradient"));
if (gradientType == QLatin1String("LinearGradient")) {
m_output << m_indent << "QLinearGradient " << gradientName
<< '(' << gradient->attributeStartX()
m_output << m_indent
<< language::stackVariableWithInitParameters("QLinearGradient", gradientName)
<< gradient->attributeStartX()
<< ", " << gradient->attributeStartY()
<< ", " << gradient->attributeEndX()
<< ", " << gradient->attributeEndY() << ");\n";
<< ", " << gradient->attributeEndY() << ')' << language::eol;
} else if (gradientType == QLatin1String("RadialGradient")) {
m_output << m_indent << "QRadialGradient " << gradientName
<< '(' << gradient->attributeCentralX()
m_output << m_indent
<< language::stackVariableWithInitParameters("QRadialGradient", gradientName)
<< gradient->attributeCentralX()
<< ", " << gradient->attributeCentralY()
<< ", " << gradient->attributeRadius()
<< ", " << gradient->attributeFocalX()
<< ", " << gradient->attributeFocalY() << ");\n";
<< ", " << gradient->attributeFocalY() << ')' << language::eol;
} else if (gradientType == QLatin1String("ConicalGradient")) {
m_output << m_indent << "QConicalGradient " << gradientName
<< '(' << gradient->attributeCentralX()
m_output << m_indent
<< language::stackVariableWithInitParameters("QConicalGradient", gradientName)
<< gradient->attributeCentralX()
<< ", " << gradient->attributeCentralY()
<< ", " << gradient->attributeAngle() << ");\n";
<< ", " << gradient->attributeAngle() << ')' << language::eol;
}
m_output << m_indent << gradientName << ".setSpread(QGradient::"
<< gradient->attributeSpread() << ");\n";
m_output << m_indent << gradientName << ".setSpread(QGradient"
<< language::qualifier << gradient->attributeSpread()
<< ')' << language::eol;
if (gradient->hasAttributeCoordinateMode()) {
m_output << m_indent << gradientName << ".setCoordinateMode(QGradient::"
<< gradient->attributeCoordinateMode() << ");\n";
m_output << m_indent << gradientName << ".setCoordinateMode(QGradient"
<< language::qualifier << gradient->attributeCoordinateMode()
<< ')' << language::eol;
}
const auto &stops = gradient->elementGradientStop();
@ -1942,19 +1968,22 @@ void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brush
const DomColor *color = stop->elementColor();
m_output << m_indent << gradientName << ".setColorAt("
<< stop->attributePosition() << ", "
<< domColor2QString(color) << ");\n";
<< domColor2QString(color) << ')' << language::eol;
}
m_output << m_indent << "QBrush " << brushName << '('
<< gradientName << ");\n";
m_output << m_indent
<< language::stackVariableWithInitParameters("QBrush", brushName)
<< gradientName << ')' << language::eol;
} else if (style == QLatin1String("TexturePattern")) {
const DomProperty *property = brush->elementTexture();
const QString iconValue = iconCall(property);
m_output << m_indent << "QBrush " << brushName << " = QBrush("
<< iconValue << ");\n";
m_output << m_indent
<< language::stackVariableWithInitParameters("QBrush", brushName)
<< iconValue << ')' << language::eol;
} else {
const DomColor *color = brush->elementColor();
m_output << m_indent << "QBrush " << brushName << '('
m_output << m_indent
<< language::stackVariableWithInitParameters("QBrush", brushName)
<< domColor2QString(color) << ')' << language::eol;
m_output << m_indent << brushName << ".setStyle("

View File

@ -31,7 +31,7 @@
class StaticPlugin : public QObject
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "SomeIID")
Q_PLUGIN_METADATA(IID "SomeIID" URI "qt.test.pluginloader.staticplugin")
public:
StaticPlugin() {}
};

View File

@ -552,6 +552,7 @@ void tst_QPluginLoader::staticPlugins()
QCOMPARE(metaData.value("version").toInt(), QT_VERSION);
QCOMPARE(metaData.value("IID").toString(), "SomeIID");
QCOMPARE(metaData.value("ExtraMetaData"), QJsonArray({ "StaticPlugin", "foo" }));
QCOMPARE(metaData.value("URI").toString(), "qt.test.pluginloader.staticplugin");
}

View File

@ -70,6 +70,7 @@ private slots:
void setBlue();
void setRgb();
void setRgbF();
void setRgba();
void setHsv();
void setCmyk();
@ -187,28 +188,28 @@ void tst_QColor::getSetCheck()
// void QColor::setRedF(qreal)
obj1.setRedF(0.0);
QCOMPARE(obj1.redF(), qreal(0.0));
obj1.setRedF(-0.2);
QCOMPARE(obj1.redF(), qreal(0.0)); // range<0.0, 1.0
obj1.setRedF(1.1);
QCOMPARE(obj1.redF(), qreal(1.0)); // range<0.0, 1.0
obj1.setRedF(-0.25);
QCOMPARE(obj1.redF(), qreal(-0.25));
obj1.setRedF(1.25);
QCOMPARE(obj1.redF(), qreal(1.25));
// qreal QColor::greenF()
// void QColor::setGreenF(qreal)
obj1.setGreenF(0.0);
QCOMPARE(obj1.greenF(), qreal(0.0));
obj1.setGreenF(-0.2);
QCOMPARE(obj1.greenF(), qreal(0.0)); // range<0.0, 1.0
obj1.setGreenF(1.1);
QCOMPARE(obj1.greenF(), qreal(1.0)); // range<0.0, 1.0
obj1.setGreenF(-0.25);
QCOMPARE(obj1.greenF(), qreal(-0.25));
obj1.setGreenF(1.5);
QCOMPARE(obj1.greenF(), qreal(1.5));
// qreal QColor::blueF()
// void QColor::setBlueF(qreal)
obj1.setBlueF(0.0);
QCOMPARE(obj1.blueF(), qreal(0.0));
obj1.setBlueF(-0.2);
QCOMPARE(obj1.blueF(), qreal(0.0)); // range<0.0, 1.0
obj1.setBlueF(1.1);
QCOMPARE(obj1.blueF(), qreal(1.0)); // range<0.0, 1.0
obj1.setBlueF(-0.5);
QCOMPARE(obj1.blueF(), qreal(-0.5));
obj1.setBlueF(2.0);
QCOMPARE(obj1.blueF(), qreal(2.0));
// QRgb QColor::rgba()
// void QColor::setRgba(QRgb)
@ -677,30 +678,81 @@ void tst_QColor::setRgb()
{
QColor color;
for (int a = 0; a <= 255; ++a) {
QRgb rgb = qRgba(0, 0, 0, a);
color.setRgb(0, 0, 0, a);
QCOMPARE(color.alpha(), a);
QCOMPARE(color.rgb(), qRgb(0, 0, 0));
color.setRgb(rgb);
QCOMPARE(color.alpha(), 255);
QCOMPARE(color.rgb(), qRgb(0, 0, 0));
int r, g, b, a2;
color.setRgb(0, 0, 0, a);
color.getRgb(&r, &g, &b, &a2);
QCOMPARE(a2, a);
QColor c(0, 0, 0);
c.setAlpha(a);
QCOMPARE(c.alpha(), a);
}
for (int r = 0; r <= 255; ++r) {
QRgb rgb = qRgb(r, 0, 0);
color.setRgb(r, 0, 0);
QCOMPARE(color.red(), r);
QCOMPARE(color.rgb(), rgb);
color.setRgb(rgb);
QCOMPARE(color.red(), r);
QCOMPARE(color.rgb(), rgb);
int r2, g, b, a;
color.getRgb(&r2, &g, &b, &a);
QCOMPARE(r2, r);
}
for (int g = 0; g <= 255; ++g) {
QRgb rgb = qRgb(0, g, 0);
color.setRgb(0, g, 0);
QCOMPARE(color.green(), g);
QCOMPARE(color.rgb(), rgb);
color.setRgb(rgb);
QCOMPARE(color.green(), g);
QCOMPARE(color.rgb(), rgb);
int r, g2, b, a;
color.getRgb(&r, &g2, &b, &a);
QCOMPARE(g2, g);
}
for (int b = 0; b <= 255; ++b) {
QRgb rgb = qRgb(0, 0, b);
color.setRgb(0, 0, b);
QCOMPARE(color.blue(), b);
QCOMPARE(color.rgb(), rgb);
color.setRgb(rgb);
QCOMPARE(color.blue(), b);
QCOMPARE(color.rgb(), rgb);
int r, g, b2, a;
color.getRgb(&r, &g, &b2, &a);
QCOMPARE(b2, b);
}
}
void tst_QColor::setRgbF()
{
QColor color;
for (int A = 0; A <= USHRT_MAX; ++A) {
{
// 0-255
int a = A >> 8;
QRgb rgb = qRgba(0, 0, 0, a);
color.setRgb(0, 0, 0, a);
QCOMPARE(color.alpha(), a);
QCOMPARE(color.rgb(), qRgb(0, 0, 0));
color.setRgb(rgb);
QCOMPARE(color.alpha(), 255);
QCOMPARE(color.rgb(), qRgb(0, 0, 0));
int r, g, b, a2;
color.setRgb(0, 0, 0, a);
color.getRgb(&r, &g, &b, &a2);
QCOMPARE(a2, a);
QColor c(0, 0, 0);
c.setAlpha(a);
QCOMPARE(c.alpha(), a);
}
{
// 0.0-1.0
qreal a = A / qreal(USHRT_MAX);
@ -719,24 +771,6 @@ void tst_QColor::setRgb()
}
for (int R = 0; R <= USHRT_MAX; ++R) {
{
// 0-255
int r = R >> 8;
QRgb rgb = qRgb(r, 0, 0);
color.setRgb(r, 0, 0);
QCOMPARE(color.red(), r);
QCOMPARE(color.rgb(), rgb);
color.setRgb(rgb);
QCOMPARE(color.red(), r);
QCOMPARE(color.rgb(), rgb);
int r2, g, b, a;
color.getRgb(&r2, &g, &b, &a);
QCOMPARE(r2, r);
}
{
// 0.0-1.0
qreal r = R / qreal(USHRT_MAX);
@ -750,24 +784,6 @@ void tst_QColor::setRgb()
}
for (int G = 0; G <= USHRT_MAX; ++G) {
{
// 0-255
int g = G >> 8;
QRgb rgb = qRgb(0, g, 0);
color.setRgb(0, g, 0);
QCOMPARE(color.green(), g);
QCOMPARE(color.rgb(), rgb);
color.setRgb(rgb);
QCOMPARE(color.green(), g);
QCOMPARE(color.rgb(), rgb);
int r, g2, b, a;
color.getRgb(&r, &g2, &b, &a);
QCOMPARE(g2, g);
}
{
// 0.0-1.0
qreal g = G / qreal(USHRT_MAX);
@ -781,24 +797,6 @@ void tst_QColor::setRgb()
}
for (int B = 0; B <= USHRT_MAX; ++B) {
{
// 0-255
int b = B >> 8;
QRgb rgb = qRgb(0, 0, b);
color.setRgb(0, 0, b);
QCOMPARE(color.blue(), b);
QCOMPARE(color.rgb(), rgb);
color.setRgb(rgb);
QCOMPARE(color.blue(), b);
QCOMPARE(color.rgb(), rgb);
int r, g, b2, a;
color.getRgb(&r, &g, &b2, &a);
QCOMPARE(b2, b);
}
{
// 0.0-1.0
qreal b = B / qreal(USHRT_MAX);
@ -810,6 +808,45 @@ void tst_QColor::setRgb()
QCOMPARE(b2, b);
}
}
for (int R = -128; R <= 512; ++R) {
{
// extended RGB
qreal r = R / qreal(256);
color.setRgbF(r, 0.0, 0.0);
QCOMPARE(qfloat16(color.redF()), qfloat16(r));
qreal r2, g, b, a;
color.getRgbF(&r2, &g, &b, &a);
QCOMPARE(qfloat16(r2), qfloat16(r));
}
}
for (int G = -128; G <= 512; ++G) {
{
// extended RGB
qreal g = G / qreal(256);
color.setRgbF(0.0, g, 0.0);
QCOMPARE(qfloat16(color.greenF()), qfloat16(g));
qreal r, g2, b, a;
color.getRgbF(&r, &g2, &b, &a);
QCOMPARE(qfloat16(g2), qfloat16(g));
}
}
for (int B = -128; B <= 512; ++B) {
{
// extended RGB
qreal b = B / qreal(256);
color.setRgbF(0.0, 0.0, b);
QCOMPARE(qfloat16(color.blueF()), qfloat16(b));
qreal r, g, b2, a;
color.getRgbF(&r, &g, &b2, &a);
QCOMPARE(qfloat16(b2), qfloat16(b));
}
}
}
void tst_QColor::setRgba()

View File

@ -57,6 +57,8 @@ private slots:
void imageConversion();
void loadImage();
void gamut();
};
tst_QColorSpace::tst_QColorSpace()
@ -232,6 +234,59 @@ void tst_QColorSpace::loadImage()
// Test the iccProfile getter returns the ICC profile from the image
// which since we didn't write it, isn't identical to our defaults.
QVERIFY(defaultProPhotoRgb.iccProfile() != image.colorSpace().iccProfile());
QColorTransform transform = image.colorSpace().transformationToColorSpace(QColorSpace::SRgb);
qreal maxRed = 0;
qreal maxBlue = 0;
qreal maxRed2 = 0;
qreal maxBlue2 = 0;
for (int y = 0; y < image.height(); ++y) {
for (int x = 0; x < image.width(); ++x) {
QColor p = image.pixelColor(x, y);
maxRed = std::max(maxRed, p.redF());
maxBlue = std::max(maxBlue, p.blueF());
p = transform.map(p);
maxRed2 = std::max(maxRed2, p.redF());
maxBlue2 = std::max(maxBlue2, p.blueF());
}
}
// ProPhotoRgb can be a lot more red and blue than SRgb can, so it will have lower values.
QVERIFY(maxRed2 > maxRed);
QVERIFY(maxBlue2 > maxBlue);
}
void tst_QColorSpace::gamut()
{
QColor black = QColor::fromRgbF(0.0, 0.0, 0.0);
QColor white = QColor::fromRgbF(1.0, 1.0, 1.0);
QColor red = QColor::fromRgbF(1.0, 0.0, 0.0);
QColor green = QColor::fromRgbF(0.0, 1.0, 0.0);
QColor blue = QColor::fromRgbF(0.0, 0.0, 1.0);
QColorTransform toAdobeRgb = QColorSpace(QColorSpace::SRgb).transformationToColorSpace(QColorSpace::AdobeRgb);
QColor tblack = toAdobeRgb.map(black);
QColor twhite = toAdobeRgb.map(white);
QColor tred = toAdobeRgb.map(red);
QColor tgreen = toAdobeRgb.map(green);
QColor tblue = toAdobeRgb.map(blue);
// Black is black
QCOMPARE(tblack, black);
// This white hasn't changed
QCOMPARE(twhite, white);
// Adobe's red and blue gamut corners are the same as sRGB's
// So, a color in the red corner, will stay in the red corner
// the same for blue, but not for green.
QVERIFY(tred.greenF() < 0.001);
QVERIFY(tred.blueF() < 0.001);
QVERIFY(tblue.redF() < 0.001);
QVERIFY(tblue.greenF() < 0.001);
QVERIFY(tgreen.redF() > 0.2);
QVERIFY(tgreen.blueF() > 0.2);
}
QTEST_MAIN(tst_QColorSpace)

View File

@ -36,17 +36,27 @@
#include <QtCore/QTemporaryDir>
#include <QtCore/QRegularExpression>
#include <QtCore/QStandardPaths>
#include <QtCore/QVector>
#include <cstdio>
static const char keepEnvVar[] = "UIC_KEEP_GENERATED_FILES";
static const char diffToStderrEnvVar[] = "UIC_STDERR_DIFF";
struct TestEntry
{
QByteArray name;
QString baselineBaseName;
QString generatedFileName;
};
class tst_uic : public QObject
{
Q_OBJECT
public:
using TestEntries = QVector<TestEntry>;
tst_uic();
private Q_SLOTS:
@ -63,13 +73,20 @@ private Q_SLOTS:
void compare();
void compare_data() const;
void python();
void python_data() const;
void runCompare();
private:
void populateTestEntries();
const QString m_command;
QString m_baseline;
QTemporaryDir m_generated;
TestEntries m_testEntries;
QRegularExpression m_versionRegexp;
QString m_python;
};
tst_uic::tst_uic()
@ -85,6 +102,32 @@ static QByteArray msgProcessStartFailed(const QString &command, const QString &w
return result.toLocal8Bit();
}
// Locate Python and check whether PySide2 is installed
static QString locatePython(QTemporaryDir &generatedDir)
{
QString python = QStandardPaths::findExecutable(QLatin1String("python"));
if (python.isEmpty()) {
qWarning("Cannot locate python, skipping tests");
return QString();
}
QFile importTestFile(generatedDir.filePath(QLatin1String("import_test.py")));
if (!importTestFile.open(QIODevice::WriteOnly| QIODevice::Text))
return QString();
importTestFile.write("import PySide2.QtCore\n");
importTestFile.close();
QProcess process;
process.start(python, {importTestFile.fileName()});
if (!process.waitForStarted() || !process.waitForFinished())
return QString();
if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) {
const QString stdErr = QString::fromLocal8Bit(process.readAllStandardError()).simplified();
qWarning("PySide2 is not installed (%s)", qPrintable(stdErr));
return QString();
}
importTestFile.remove();
return python;
}
void tst_uic::initTestCase()
{
QVERIFY2(m_generated.isValid(), qPrintable(m_generated.errorString()));
@ -105,7 +148,28 @@ void tst_uic::initTestCase()
arg(QDir::currentPath());
if (!outLines.empty())
msg += outLines.front();
populateTestEntries();
QVERIFY(!m_testEntries.isEmpty());
qDebug("%s", qPrintable(msg));
m_python = locatePython(m_generated);
}
void tst_uic::populateTestEntries()
{
const QString generatedPrefix = m_generated.path() + QLatin1Char('/');
QDir baseline(m_baseline);
const QString baseLinePrefix = baseline.path() + QLatin1Char('/');
const QFileInfoList baselineFiles =
baseline.entryInfoList(QStringList(QString::fromLatin1("*.ui")), QDir::Files);
m_testEntries.reserve(baselineFiles.size());
for (const QFileInfo &baselineFile : baselineFiles) {
const QString baseName = baselineFile.baseName();
const QString baselineBaseName = baseLinePrefix + baseName;
const QString generatedFile = generatedPrefix + baselineFile.fileName()
+ QLatin1String(".h");
m_testEntries.append(TestEntry{baseName.toLocal8Bit(), baselineBaseName, generatedFile});
}
}
static const char helpFormat[] = R"(
@ -171,22 +235,12 @@ void tst_uic::run_data() const
QTest::addColumn<QString>("generatedFile");
QTest::addColumn<QStringList>("options");
QDir generated(m_generated.path());
QDir baseline(m_baseline);
const QFileInfoList baselineFiles = baseline.entryInfoList(QStringList("*.ui"), QDir::Files);
foreach (const QFileInfo &baselineFile, baselineFiles) {
const QString generatedFile = generated.absolutePath()
+ QLatin1Char('/') + baselineFile.fileName()
+ QLatin1String(".h");
for (const TestEntry &te : m_testEntries) {
QStringList options;
if (baselineFile.fileName() == QLatin1String("qttrid.ui"))
if (te.name == QByteArrayLiteral("qttrid"))
options << QStringList(QLatin1String("-idbased"));
QTest::newRow(qPrintable(baselineFile.baseName()))
<< baselineFile.absoluteFilePath()
<< generatedFile
<< options;
QTest::newRow(te.name.constData()) << (te.baselineBaseName + QLatin1String(".ui"))
<< te.generatedFileName << options;
}
}
@ -264,15 +318,9 @@ void tst_uic::compare_data() const
QTest::addColumn<QString>("originalFile");
QTest::addColumn<QString>("generatedFile");
QDir generated(m_generated.path());
QDir baseline(m_baseline);
const QFileInfoList baselineFiles = baseline.entryInfoList(QStringList("*.h"), QDir::Files);
foreach (const QFileInfo &baselineFile, baselineFiles) {
const QString generatedFile = generated.absolutePath()
+ QLatin1Char('/') + baselineFile.fileName();
QTest::newRow(qPrintable(baselineFile.baseName()))
<< baselineFile.absoluteFilePath()
<< generatedFile;
for (const TestEntry &te : m_testEntries) {
QTest::newRow(te.name.constData()) << (te.baselineBaseName + QLatin1String(".ui.h"))
<< te.generatedFileName;
}
}
@ -280,7 +328,7 @@ void tst_uic::runTranslation()
{
QProcess process;
QDir baseline(m_baseline);
const QDir baseline(m_baseline);
QDir generated(m_generated.path());
generated.mkdir(QLatin1String("translation"));
@ -327,5 +375,75 @@ void tst_uic::runCompare()
QCOMPARE(generatedFileContents, originalFileContents);
}
// Let uic generate Python code and verify that it is syntactically
// correct by compiling it into .pyc. This test is executed only
// when python with an installed Qt for Python is detected (see locatePython()).
static inline QByteArray msgCompilePythonFailed(const QByteArray &error)
{
// If there is a line with blanks and caret indicating an error in the line
// above, insert the cursor into the offending line and remove the caret.
QByteArrayList lines = error.trimmed().split('\n');
for (int i = lines.size() - 1; i > 0; --i) {
const auto &line = lines.at(i);
const int caret = line.indexOf('^');
if (caret == 0 || (caret > 0 && line.at(caret - 1) == ' ')) {
lines.removeAt(i);
lines[i - 1].insert(caret, '|');
break;
}
}
return lines.join('\n');
}
void tst_uic::python_data() const
{
QTest::addColumn<QString>("originalFile");
QTest::addColumn<QString>("generatedFile");
const int size = m_python.isEmpty()
? qMin(1, m_testEntries.size()) : m_testEntries.size();
for (int i = 0; i < size; ++i) {
const TestEntry &te = m_testEntries.at(i);
// qprintsettingsoutput: variable named 'from' clashes with Python
if (!te.baselineBaseName.endsWith(QLatin1String("/qprintsettingsoutput"))) {
QString generatedFile = te.generatedFileName;
generatedFile.chop(1); // foo.h -> foo.py
generatedFile.append(QLatin1String("py"));
QTest::newRow(te.name.constData())
<< (te.baselineBaseName + QLatin1String(".ui"))
<< generatedFile;
}
}
}
void tst_uic::python()
{
QFETCH(QString, originalFile);
QFETCH(QString, generatedFile);
if (m_python.isEmpty())
QSKIP("Python was not found");
QStringList uicArguments{QLatin1String("-g"), QLatin1String("python"),
originalFile, QLatin1String("-o"), generatedFile};
QProcess process;
process.setWorkingDirectory(m_generated.path());
process.start(m_command, uicArguments);
QVERIFY2(process.waitForStarted(), msgProcessStartFailed(m_command, process.errorString()));
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 0);
QVERIFY(QFileInfo::exists(generatedFile));
// Test Python code generation by compiling the file
QStringList compileArguments{QLatin1String("-m"), QLatin1String("py_compile"), generatedFile};
process.start(m_python, compileArguments);
QVERIFY2(process.waitForStarted(), msgProcessStartFailed(m_command, process.errorString()));
QVERIFY(process.waitForFinished());
const bool compiled = process.exitStatus() == QProcess::NormalExit
&& process.exitCode() == 0;
QVERIFY2(compiled, msgCompilePythonFailed(process.readAllStandardError()).constData());
}
QTEST_MAIN(tst_uic)
#include "tst_uic.moc"

View File

@ -2418,8 +2418,8 @@ void tst_QWidget::showMinimizedKeepsFocus()
{
if (m_platform == QStringLiteral("xcb"))
QSKIP("QTBUG-26424");
if (m_platform == QStringLiteral("wayland"))
QSKIP("Wayland: This fails. Figure out why.");
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("Window activation is not supported.");
if (m_platform == QStringLiteral("offscreen"))
QSKIP("Platform offscreen does not support showMinimized()");
@ -2625,8 +2625,8 @@ void tst_QWidget::icon()
void tst_QWidget::hideWhenFocusWidgetIsChild()
{
if (m_platform == QStringLiteral("wayland"))
QSKIP("Wayland: This fails. Figure out why.");
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("Window activation is not supported.");
QScopedPointer<QWidget> testWidget(new QWidget);
testWidget->setWindowTitle(__FUNCTION__);
@ -5433,8 +5433,8 @@ void tst_QWidget::multipleToplevelFocusCheck()
QSKIP("QTBUG-52974");
#endif
if (m_platform == QStringLiteral("wayland"))
QSKIP("Wayland: This fails. Figure out why.");
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("Window activation is not supported");
else if (m_platform == QStringLiteral("winrt"))
QSKIP("Winrt: Sometimes crashes in QTextLayout. - QTBUG-68297");
TopLevelFocusCheck w1;
@ -9535,8 +9535,8 @@ void tst_QWidget::setGraphicsEffect()
void tst_QWidget::activateWindow()
{
if (m_platform == QStringLiteral("wayland"))
QSKIP("Wayland: This fails. Figure out why.");
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("Window activation is not supported.");
// Test case for QTBUG-26711
@ -9603,8 +9603,8 @@ void tst_QWidget::openModal_taskQTBUG_5804()
void tst_QWidget::focusProxyAndInputMethods()
{
if (m_platform == QStringLiteral("wayland"))
QSKIP("Wayland: This fails. Figure out why.");
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("Window activation is not supported.");
QScopedPointer<QWidget> toplevel(new QWidget(0, Qt::X11BypassWindowManagerHint));
toplevel->resize(200, 200);
toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);