This makes QFont do a "light" detach when the font attributes data has been changed.
The new test clearly shows that the engine is now shared between
two font instances after changing the kerning attribute.
Change-Id: I59db822f459f02d111686dba7101b98e361fada9
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
}
/*!
+ \internal
+ Detaches the font object from common font attributes data.
+ Call this instead of QFont::detach() if the only font attributes data
+ has been changed (underline, letterSpacing, kerning, etc.).
+*/
+void QFontPrivate::detachButKeepEngineData(QFont *font)
+{
+ if (font->d->ref.load() == 1)
+ return;
+
+ QFontEngineData *engineData = font->d->engineData;
+ if (engineData)
+ engineData->ref.ref();
+ font->d.detach();
+ font->d->engineData = engineData;
+}
+
+/*!
Constructs a font object that uses the application's default font.
\sa QGuiApplication::setFont(), QGuiApplication::font()
if ((resolve_mask & QFont::UnderlineResolved) && d->underline == enable)
return;
- detach();
+ QFontPrivate::detachButKeepEngineData(this);
d->underline = enable;
resolve_mask |= QFont::UnderlineResolved;
if ((resolve_mask & QFont::OverlineResolved) && d->overline == enable)
return;
- detach();
+ QFontPrivate::detachButKeepEngineData(this);
d->overline = enable;
resolve_mask |= QFont::OverlineResolved;
if ((resolve_mask & QFont::StrikeOutResolved) && d->strikeOut == enable)
return;
- detach();
+ QFontPrivate::detachButKeepEngineData(this);
d->strikeOut = enable;
resolve_mask |= QFont::StrikeOutResolved;
if ((resolve_mask & QFont::KerningResolved) && d->kerning == enable)
return;
- detach();
+ QFontPrivate::detachButKeepEngineData(this);
d->kerning = enable;
resolve_mask |= QFont::KerningResolved;
d->letterSpacing == newSpacing)
return;
- detach();
+ QFontPrivate::detachButKeepEngineData(this);
d->letterSpacing = newSpacing;
d->letterSpacingIsAbsolute = absoluteSpacing;
d->wordSpacing == newSpacing)
return;
- detach();
+ QFontPrivate::detachButKeepEngineData(this);
d->wordSpacing = newSpacing;
resolve_mask |= QFont::WordSpacingResolved;
capitalization() == caps)
return;
- detach();
+ QFontPrivate::detachButKeepEngineData(this);
d->capital = caps;
resolve_mask |= QFont::CapitalizationResolved;
{
if ((bool) d->rawMode == enable) return;
+ // might change behavior, thus destroy engine data
detach();
d->rawMode = enable;
}
void resolve(uint mask, const QFontPrivate *other);
+
+ static void detachButKeepEngineData(QFont *font);
+
private:
QFontPrivate &operator=(const QFontPrivate &) { return *this; }
};
CONFIG += parallel_test
TARGET = tst_qfont
QT += testlib
+QT += core-private gui-private
!contains(QT_CONFIG, no-widgets): QT += widgets
SOURCES += tst_qfont.cpp
#include <qfont.h>
+#include <private/qfont_p.h>
#include <qfontdatabase.h>
#include <qfontinfo.h>
#include <qstringlist.h>
void styleName();
void defaultFamily_data();
void defaultFamily();
+
+ void sharing();
};
// Testing get/set functions
QVERIFY2(isAcceptable, msgNotAcceptableFont(familyForHint, acceptableFamilies));
}
+void tst_QFont::sharing()
+{
+ QFont f;
+ f.setStyleHint(QFont::Serif);
+ f.exactMatch(); // loads engine
+ QCOMPARE(QFontPrivate::get(f)->ref.load(), 1);
+ QVERIFY(QFontPrivate::get(f)->engineData);
+ QCOMPARE(QFontPrivate::get(f)->engineData->ref.load(), 1);
+
+ QFont f2(f);
+ QVERIFY(QFontPrivate::get(f2) == QFontPrivate::get(f));
+ QCOMPARE(QFontPrivate::get(f2)->ref.load(), 2);
+ QVERIFY(QFontPrivate::get(f2)->engineData);
+ QVERIFY(QFontPrivate::get(f2)->engineData == QFontPrivate::get(f)->engineData);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 1);
+
+ f2.setKerning(!f.kerning());
+ QVERIFY(QFontPrivate::get(f2) != QFontPrivate::get(f));
+ QCOMPARE(QFontPrivate::get(f2)->ref.load(), 1);
+ QVERIFY(QFontPrivate::get(f2)->engineData);
+ QVERIFY(QFontPrivate::get(f2)->engineData == QFontPrivate::get(f)->engineData);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 2);
+
+ f2 = f;
+ QVERIFY(QFontPrivate::get(f2) == QFontPrivate::get(f));
+ QCOMPARE(QFontPrivate::get(f2)->ref.load(), 2);
+ QVERIFY(QFontPrivate::get(f2)->engineData);
+ QVERIFY(QFontPrivate::get(f2)->engineData == QFontPrivate::get(f)->engineData);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 1);
+
+ if (f.pointSize() > 0)
+ f2.setPointSize(f.pointSize() * 2 / 3);
+ else
+ f2.setPixelSize(f.pixelSize() * 2 / 3);
+ QVERIFY(QFontPrivate::get(f2) != QFontPrivate::get(f));
+ QCOMPARE(QFontPrivate::get(f2)->ref.load(), 1);
+ QVERIFY(!QFontPrivate::get(f2)->engineData);
+ QVERIFY(QFontPrivate::get(f2)->engineData != QFontPrivate::get(f)->engineData);
+}
+
QTEST_MAIN(tst_QFont)
#include "tst_qfont.moc"