summaryrefslogtreecommitdiffstats
path: root/src/gui/text
diff options
context:
space:
mode:
authorDavid Boddie <dboddie@trolltech.com>2010-03-30 14:56:41 (GMT)
committerDavid Boddie <dboddie@trolltech.com>2010-03-30 14:56:41 (GMT)
commit87f66d52e362de003a9f2cdaafbfbe3ba4e5fbc3 (patch)
treef8b8c24056d54e19937dea1b0301af558597726a /src/gui/text
parent09ce407aaa4a00013a606bf0011faf6cbc654c72 (diff)
parent00f7426f3906361fb5addb36e428648eee5e2983 (diff)
downloadQt-87f66d52e362de003a9f2cdaafbfbe3ba4e5fbc3.zip
Qt-87f66d52e362de003a9f2cdaafbfbe3ba4e5fbc3.tar.gz
Qt-87f66d52e362de003a9f2cdaafbfbe3ba4e5fbc3.tar.bz2
Merge branch '4.7' of git@scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.7
Conflicts: doc/src/modules.qdoc mkspecs/common/symbian/symbian.conf src/gui/graphicsview/qgraphicswidget.h src/s60installs/bwins/QtGuiu.def src/s60installs/eabi/QtGuiu.def
Diffstat (limited to 'src/gui/text')
-rw-r--r--src/gui/text/qfont.cpp4
-rw-r--r--src/gui/text/qfont.h24
-rw-r--r--src/gui/text/qfont_s60.cpp4
-rw-r--r--src/gui/text/qfontdatabase_qws.cpp7
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp4
-rw-r--r--src/gui/text/qfontdatabase_win.cpp1
-rw-r--r--src/gui/text/qfontdatabase_x11.cpp8
-rw-r--r--src/gui/text/qfontengine.cpp10
-rw-r--r--src/gui/text/qfontengine_ft.cpp72
-rw-r--r--src/gui/text/qfontengine_ft_p.h16
-rw-r--r--src/gui/text/qfontengine_mac.mm102
-rw-r--r--src/gui/text/qfontengine_qpf.cpp14
-rw-r--r--src/gui/text/qfontengine_win.cpp6
-rw-r--r--src/gui/text/qfontmetrics.cpp18
-rw-r--r--src/gui/text/qstatictext.cpp654
-rw-r--r--src/gui/text/qstatictext.h106
-rw-r--r--src/gui/text/qstatictext_p.h151
-rw-r--r--src/gui/text/qsyntaxhighlighter.cpp95
-rw-r--r--src/gui/text/qtextcontrol.cpp23
-rw-r--r--src/gui/text/qtextcontrol_p.h3
-rw-r--r--src/gui/text/qtextcursor.cpp26
-rw-r--r--src/gui/text/qtextcursor.h1
-rw-r--r--src/gui/text/qtextdocument.cpp33
-rw-r--r--src/gui/text/qtextdocument.h7
-rw-r--r--src/gui/text/qtextdocument_p.cpp65
-rw-r--r--src/gui/text/qtextdocument_p.h3
-rw-r--r--src/gui/text/qtextengine.cpp14
-rw-r--r--src/gui/text/qtextengine_p.h1
-rw-r--r--src/gui/text/qtextlayout.cpp15
-rw-r--r--src/gui/text/qtextlayout.h1
-rw-r--r--src/gui/text/qzip.cpp44
-rw-r--r--src/gui/text/qzipreader_p.h9
-rw-r--r--src/gui/text/qzipwriter_p.h2
-rw-r--r--src/gui/text/text.pri7
34 files changed, 1386 insertions, 164 deletions
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index dd9e69e..99b9f40 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -73,7 +73,7 @@
#endif
#endif
#ifdef Q_OS_SYMBIAN
-#include "qt_s60_p.h"
+#include <private/qt_s60_p.h>
#endif
#include <QMutexLocker>
@@ -1297,6 +1297,8 @@ QFont::StyleHint QFont::styleHint() const
\value PreferQuality prefer the best quality font. The font matcher
will use the nearest standard point size that the font
supports.
+ \value ForceIntegerMetrics forces the use of integer values in font engines that support fractional
+ font metrics.
*/
/*!
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index a2fff70..6f62424 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -76,17 +76,18 @@ public:
};
enum StyleStrategy {
- PreferDefault = 0x0001,
- PreferBitmap = 0x0002,
- PreferDevice = 0x0004,
- PreferOutline = 0x0008,
- ForceOutline = 0x0010,
- PreferMatch = 0x0020,
- PreferQuality = 0x0040,
- PreferAntialias = 0x0080,
- NoAntialias = 0x0100,
- OpenGLCompatible = 0x0200,
- NoFontMerging = 0x8000
+ PreferDefault = 0x0001,
+ PreferBitmap = 0x0002,
+ PreferDevice = 0x0004,
+ PreferOutline = 0x0008,
+ ForceOutline = 0x0010,
+ PreferMatch = 0x0020,
+ PreferQuality = 0x0040,
+ PreferAntialias = 0x0080,
+ NoAntialias = 0x0100,
+ OpenGLCompatible = 0x0200,
+ ForceIntegerMetrics = 0x0400,
+ NoFontMerging = 0x8000
};
enum Weight {
@@ -291,6 +292,7 @@ private:
friend class QFontMetricsF;
friend class QFontInfo;
friend class QPainter;
+ friend class QPainterPrivate;
friend class QPSPrintEngineFont;
friend class QApplication;
friend class QWidget;
diff --git a/src/gui/text/qfont_s60.cpp b/src/gui/text/qfont_s60.cpp
index 52c77d6..ccd17a2 100644
--- a/src/gui/text/qfont_s60.cpp
+++ b/src/gui/text/qfont_s60.cpp
@@ -40,8 +40,8 @@
****************************************************************************/
#include "qfont.h"
-#include "qt_s60_p.h"
-#include "qpixmap_s60_p.h"
+#include <private/qt_s60_p.h>
+#include <private/qpixmap_s60_p.h>
#include "qmutex.h"
QT_BEGIN_NAMESPACE
diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp
index 62d7793..a3d8d65 100644
--- a/src/gui/text/qfontdatabase_qws.cpp
+++ b/src/gui/text/qfontdatabase_qws.cpp
@@ -632,8 +632,9 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
#ifndef QT_NO_FREETYPE
QScopedPointer<QFontEngineFT> fte(new QFontEngineFT(def));
- if (fte->init(faceId, style->antialiased,
- style->antialiased ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) {
+ bool antialias = style->antialiased && !(request.styleStrategy & QFont::NoAntialias);
+ if (fte->init(faceId, antialias,
+ antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) {
#ifdef QT_NO_QWS_QPF2
return fte.take();
#else
@@ -793,7 +794,7 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
" family: %s [%s], script: %d\n"
" weight: %d, style: %d\n"
" stretch: %d\n"
- " pixelSize: %d\n"
+ " pixelSize: %g\n"
" pitch: %c",
family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
index fceb401..ef5e0c4 100644
--- a/src/gui/text/qfontdatabase_s60.cpp
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -45,8 +45,8 @@
#include "qfontengine_s60_p.h"
#include "qabstractfileengine.h"
#include "qdesktopservices.h"
-#include "qpixmap_s60_p.h"
-#include "qt_s60_p.h"
+#include <private/qpixmap_s60_p.h>
+#include <private/qt_s60_p.h>
#include "qendian.h"
#include <private/qcore_symbian_p.h>
#if defined(QT_NO_FREETYPE)
diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp
index a6ceee1..c50d363 100644
--- a/src/gui/text/qfontdatabase_win.cpp
+++ b/src/gui/text/qfontdatabase_win.cpp
@@ -1111,7 +1111,6 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
if (AddFontResource((LPCWSTR)fnt->fileName.utf16()) == 0)
return;
#else
- // supported from 2000 on, so no need to deal with the *A variant
PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"),
"AddFontResourceExW");
if (!ptrAddFontResourceExW
diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp
index bb1e60d..b1ab478 100644
--- a/src/gui/text/qfontdatabase_x11.cpp
+++ b/src/gui/text/qfontdatabase_x11.cpp
@@ -41,9 +41,9 @@
#include <qplatformdefs.h>
-#include <qdatetime.h>
#include <qdebug.h>
#include <qpaintdevice.h>
+#include <qelapsedtimer.h>
#include <private/qt_x11_p.h>
#include "qx11info_x11.h"
@@ -1218,7 +1218,7 @@ static void load(const QString &family = QString(), int script = -1, bool forceX
}
#ifdef QFONTDATABASE_DEBUG
- QTime t;
+ QElapsedTimer t;
t.start();
#endif
@@ -1301,7 +1301,7 @@ static void initializeDb()
if (!db || db->count)
return;
- QTime t;
+ QElapsedTimer t;
t.start();
#ifndef QT_NO_FONTCONFIG
@@ -1314,7 +1314,7 @@ static void initializeDb()
}
loadFontConfig();
- FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", t.elapsed());
+ FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", int(t.elapsed()));
#endif
t.start();
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 629db66..194c5f3 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -596,8 +596,9 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &t)
{
QImage i = alphaMapForGlyph(glyph);
if (t.type() > QTransform::TxTranslate)
- i = i.transformed(t);
+ i = i.transformed(t).convertToFormat(QImage::Format_Indexed8);
Q_ASSERT(i.depth() <= 8); // To verify that transformed didn't change the format...
+
return i;
}
@@ -606,11 +607,14 @@ QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, int /* margin */, const Q
QImage alphaMask = alphaMapForGlyph(glyph, t);
QImage rgbMask(alphaMask.width(), alphaMask.height(), QImage::Format_RGB32);
+ QVector<QRgb> colorTable = alphaMask.colorTable();
for (int y=0; y<alphaMask.height(); ++y) {
uint *dst = (uint *) rgbMask.scanLine(y);
uchar *src = (uchar *) alphaMask.scanLine(y);
- for (int x=0; x<alphaMask.width(); ++x)
- dst[x] = qRgb(src[x], src[x], src[x]);
+ for (int x=0; x<alphaMask.width(); ++x) {
+ int val = qAlpha(colorTable.at(src[x]));
+ dst[x] = qRgb(val, val, val);
+ }
}
return rgbMask;
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 17ade64..a9def8e 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -619,7 +619,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
transform = false;
antialias = true;
freetype = 0;
- default_load_flags = 0;
+ default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
default_hint_style = HintNone;
subpixelType = Subpixel_None;
lcdFilterType = 0;
@@ -746,7 +746,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph) const
{
- Glyph *g = set->glyph_data.value(glyph);
+ Glyph *g = set->getGlyph(glyph);
if (g)
return g;
@@ -858,10 +858,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
}
}
- Glyph *g = set->glyph_data.value(glyph);
+ Glyph *g = set->getGlyph(glyph);
if (g && g->format == format) {
if (uploadToServer && !g->uploadedToServer) {
- set->glyph_data[glyph] = 0;
+ set->setGlyph(glyph, 0);
delete g;
g = 0;
} else {
@@ -1158,7 +1158,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
uploadGlyphToServer(set, glyph, g, &info, glyph_buffer_size);
}
- set->glyph_data[glyph] = g;
+ set->setGlyph(glyph, g);
return g;
}
@@ -1381,8 +1381,7 @@ QFontEngineFT::QGlyphSet *QFontEngineFT::loadTransformedGlyphSet(const QTransfor
}
gs = &transformedGlyphSets[0];
- qDeleteAll(gs->glyph_data);
- gs->glyph_data.clear();
+ gs->clear();
gs->id = allocateServerGlyphSet();
@@ -1398,7 +1397,7 @@ bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, G
FT_Face face = 0;
for (int i = 0; i < num_glyphs; ++i) {
- Glyph *glyph = gs->glyph_data.value(glyphs[i]);
+ Glyph *glyph = gs->getGlyph(glyphs[i]);
if (glyph == 0 || glyph->format != format) {
if (!face) {
face = lockFace();
@@ -1635,7 +1634,7 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlag
FT_Face face = 0;
if (flags & QTextEngine::DesignMetrics) {
for (int i = 0; i < glyphs->numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.glyph_data.value(glyphs->glyphs[i]);
+ Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
if (g) {
glyphs->advances_x[i] = QFixed::fromFixed(g->linearAdvance);
} else {
@@ -1648,7 +1647,7 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlag
}
} else {
for (int i = 0; i < glyphs->numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.glyph_data.value(glyphs->glyphs[i]);
+ Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
if (g) {
glyphs->advances_x[i] = QFixed(g->advance);
} else {
@@ -1677,7 +1676,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
QFixed ymax = 0;
QFixed xmax = 0;
for (int i = 0; i < glyphs.numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.glyph_data.value(glyphs.glyphs[i]);
+ Glyph *g = defaultGlyphSet.getGlyph(glyphs.glyphs[i]);
if (!g) {
if (!face)
face = lockFace();
@@ -1719,7 +1718,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
{
FT_Face face = 0;
glyph_metrics_t overall;
- Glyph *g = defaultGlyphSet.glyph_data.value(glyph);
+ Glyph *g = defaultGlyphSet.getGlyph(glyph);
if (!g) {
face = lockFace();
g = loadGlyph(glyph, Format_None, true);
@@ -1783,8 +1782,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr
transformedGlyphSets.prepend(QGlyphSet());
}
glyphSet = &transformedGlyphSets[0];
- qDeleteAll(glyphSet->glyph_data);
- glyphSet->glyph_data.clear();
+ glyphSet->clear();
glyphSet->id = allocateServerGlyphSet();
glyphSet->transformationMatrix = m;
}
@@ -1792,7 +1790,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr
} else {
glyphSet = &defaultGlyphSet;
}
- Glyph * g = glyphSet->glyph_data.value(glyph);
+ Glyph * g = glyphSet->getGlyph(glyph);
if (!g) {
face = lockFace();
g = loadGlyphMetrics(glyphSet, glyph);
@@ -1881,7 +1879,7 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, int margin, const QTransfor
void QFontEngineFT::removeGlyphFromCache(glyph_t glyph)
{
- delete defaultGlyphSet.glyph_data.take(glyph);
+ defaultGlyphSet.removeGlyphFromCache(glyph);
}
int QFontEngineFT::glyphCount() const
@@ -1937,11 +1935,53 @@ QFontEngineFT::QGlyphSet::QGlyphSet()
transformationMatrix.yy = 0x10000;
transformationMatrix.xy = 0;
transformationMatrix.yx = 0;
+ memset(fast_glyph_data, 0, sizeof(fast_glyph_data));
+ fast_glyph_count = 0;
}
QFontEngineFT::QGlyphSet::~QGlyphSet()
{
+ clear();
+}
+
+void QFontEngineFT::QGlyphSet::clear()
+{
+ if (fast_glyph_count > 0) {
+ for (int i = 0; i < 256; ++i) {
+ if (fast_glyph_data[i]) {
+ delete fast_glyph_data[i];
+ fast_glyph_data[i] = 0;
+ }
+ }
+ fast_glyph_count = 0;
+ }
qDeleteAll(glyph_data);
+ glyph_data.clear();
+}
+
+void QFontEngineFT::QGlyphSet::removeGlyphFromCache(int index)
+{
+ if (index < 256) {
+ if (fast_glyph_data[index]) {
+ delete fast_glyph_data[index];
+ fast_glyph_data[index] = 0;
+ if (fast_glyph_count > 0)
+ --fast_glyph_count;
+ }
+ } else {
+ delete glyph_data.take(index);
+ }
+}
+
+void QFontEngineFT::QGlyphSet::setGlyph(int index, Glyph *glyph)
+{
+ if (index < 256) {
+ if (!fast_glyph_data[index])
+ ++fast_glyph_count;
+ fast_glyph_data[index] = glyph;
+ } else {
+ glyph_data.insert(index, glyph);
+ }
}
unsigned long QFontEngineFT::allocateServerGlyphSet()
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 98dd002..12b7da8 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -180,7 +180,21 @@ public:
FT_Matrix transformationMatrix;
unsigned long id; // server sided id, GlyphSet for X11
bool outline_drawing;
+
+ void removeGlyphFromCache(int index);
+ void clear();
+ inline Glyph *getGlyph(int index) const
+ {
+ if (index < 256)
+ return fast_glyph_data[index];
+ return glyph_data.value(index);
+ }
+ void setGlyph(int index, Glyph *glyph);
+
+private:
mutable QHash<int, Glyph *> glyph_data; // maps from glyph index to glyph data
+ mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
+ mutable int fast_glyph_count;
};
virtual QFontEngine::FaceId faceId() const;
@@ -252,7 +266,7 @@ public:
QGlyphSet *defaultGlyphs() { return &defaultGlyphSet; }
GlyphFormat defaultGlyphFormat() const { return defaultFormat; }
- inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.glyph_data.value(g); }
+ inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.getGlyph(g); }
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
bool loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format = Format_Render);
diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm
index 48bc635..0bfdbc0 100644
--- a/src/gui/text/qfontengine_mac.mm
+++ b/src/gui/text/qfontengine_mac.mm
@@ -53,6 +53,7 @@
#include <qvarlengtharray.h>
#include <qdebug.h>
#include <qendian.h>
+#include <qmath.h>
#include <ApplicationServices/ApplicationServices.h>
#include <AppKit/AppKit.h>
@@ -303,12 +304,20 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
outGlyphs[idx] = tmpGlyphs[i] | fontIndex;
outAdvances_x[idx] = QFixed::fromReal(tmpPoints[i + 1].x - tmpPoints[i].x);
outAdvances_y[idx] = QFixed::fromReal(tmpPoints[i + 1].y - tmpPoints[i].y);
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ outAdvances_x[idx] = outAdvances_x[idx].round();
+ outAdvances_y[idx] = outAdvances_y[idx].round();
+ }
}
CGSize lastGlyphAdvance;
CTFontGetAdvancesForGlyphs(runFont, kCTFontHorizontalOrientation, tmpGlyphs + glyphCount - 1, &lastGlyphAdvance, 1);
outGlyphs[rtl ? 0 : (glyphCount - 1)] = tmpGlyphs[glyphCount - 1] | fontIndex;
- outAdvances_x[rtl ? 0 : (glyphCount - 1)] = QFixed::fromReal(lastGlyphAdvance.width).ceil();
+ outAdvances_x[rtl ? 0 : (glyphCount - 1)] =
+ (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(lastGlyphAdvance.width).round()
+ : QFixed::fromReal(lastGlyphAdvance.width);
}
outGlyphs += glyphCount;
outAttributes += glyphCount;
@@ -378,8 +387,11 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *, int, QGlyphLayout *, int *
glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs)
{
QFixed w;
- for (int i = 0; i < glyphs.numGlyphs; ++i)
- w += glyphs.effectiveAdvance(i);
+ for (int i = 0; i < glyphs.numGlyphs; ++i) {
+ w += (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? glyphs.effectiveAdvance(i).round()
+ : glyphs.effectiveAdvance(i);
+ }
return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0);
}
glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
@@ -393,33 +405,51 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
ret.y = -QFixed::fromReal(rect.origin.y) - ret.height;
CGSize advances[1];
CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1);
- ret.xoff = QFixed::fromReal(advances[0].width).ceil();
- ret.yoff = QFixed::fromReal(advances[0].height).ceil();
+ ret.xoff = QFixed::fromReal(advances[0].width);
+ ret.yoff = QFixed::fromReal(advances[0].height);
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ ret.xoff = ret.xoff.round();
+ ret.yoff = ret.yoff.round();
+ }
+
return ret;
}
QFixed QCoreTextFontEngine::ascent() const
{
- return QFixed::fromReal(CTFontGetAscent(ctfont)).ceil();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetAscent(ctfont)).round()
+ : QFixed::fromReal(CTFontGetAscent(ctfont));
}
QFixed QCoreTextFontEngine::descent() const
{
+ QFixed d = QFixed::fromReal(CTFontGetDescent(ctfont));
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ d = d.round();
+
// subtract a pixel to even out the historical +1 in QFontMetrics::height().
// Fix in Qt 5.
- return QFixed::fromReal(CTFontGetDescent(ctfont)).ceil() - 1;
+ return d - 1;
}
QFixed QCoreTextFontEngine::leading() const
{
- return QFixed::fromReal(CTFontGetLeading(ctfont)).ceil();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetLeading(ctfont)).round()
+ : QFixed::fromReal(CTFontGetLeading(ctfont));
}
QFixed QCoreTextFontEngine::xHeight() const
{
- return QFixed::fromReal(CTFontGetXHeight(ctfont)).ceil();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetXHeight(ctfont)).round()
+ : QFixed::fromReal(CTFontGetXHeight(ctfont));
}
QFixed QCoreTextFontEngine::averageCharWidth() const
{
// ### Need to implement properly and get the information from the OS/2 Table.
- return QFontEngine::averageCharWidth();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFontEngine::averageCharWidth().round()
+ : QFontEngine::averageCharWidth();
}
qreal QCoreTextFontEngine::maxCharWidth() const
@@ -787,6 +817,7 @@ struct QGlyphLayoutInfo
int *mappedFonts;
QTextEngine::ShaperFlags flags;
QFontEngineMacMulti::ShaperItem *shaperItem;
+ unsigned int styleStrategy;
};
static OSStatus atsuPostLayoutCallback(ATSULayoutOperationSelector selector, ATSULineRef lineRef, URefCon refCon,
@@ -856,6 +887,11 @@ static OSStatus atsuPostLayoutCallback(ATSULayoutOperationSelector selector, ATS
QFixed yAdvance = FixedToQFixed(baselineDeltas[glyphIdx]);
QFixed xAdvance = FixedToQFixed(layoutData[glyphIdx + 1].realPos - layoutData[glyphIdx].realPos);
+ if (nfo->styleStrategy & QFont::ForceIntegerMetrics) {
+ yAdvance = yAdvance.round();
+ xAdvance = xAdvance.round();
+ }
+
if (glyphId != 0xffff || i == 0) {
if (i < nfo->glyphs->numGlyphs)
{
@@ -1032,6 +1068,7 @@ bool QFontEngineMacMulti::stringToCMapInternal(const QChar *str, int len, QGlyph
nfo.callbackCalled = false;
nfo.flags = flags;
nfo.shaperItem = shaperItem;
+ nfo.styleStrategy = fontDef.styleStrategy;
int prevNumGlyphs = *nglyphs;
@@ -1061,8 +1098,6 @@ bool QFontEngineMacMulti::stringToCMapInternal(const QChar *str, int len, QGlyph
| kATSLineDisableAllJustification
;
- layopts |= kATSLineUseDeviceMetrics;
-
if (fontDef.styleStrategy & QFont::NoAntialias)
layopts |= kATSLineNoAntiAliasing;
@@ -1366,14 +1401,22 @@ void QFontEngineMac::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla
for (int i = 0; i < glyphs->numGlyphs; ++i) {
glyphs->advances_x[i] = QFixed::fromReal(metrics[i].deviceAdvance.x);
glyphs->advances_y[i] = QFixed::fromReal(metrics[i].deviceAdvance.y);
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ glyphs->advances_x[i] = glyphs->advances_x[i].round();
+ glyphs->advances_y[i] = glyphs->advances_y[i].round();
+ }
}
}
glyph_metrics_t QFontEngineMac::boundingBox(const QGlyphLayout &glyphs)
{
QFixed w;
- for (int i = 0; i < glyphs.numGlyphs; ++i)
- w += glyphs.effectiveAdvance(i);
+ for (int i = 0; i < glyphs.numGlyphs; ++i) {
+ w += (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? glyphs.effectiveAdvance(i).round()
+ : glyphs.effectiveAdvance(i);
+ }
return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0);
}
@@ -1398,39 +1441,58 @@ glyph_metrics_t QFontEngineMac::boundingBox(glyph_t glyph)
gm.xoff = QFixed::fromReal(metrics.deviceAdvance.x);
gm.yoff = QFixed::fromReal(metrics.deviceAdvance.y);
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ gm.x = gm.x.floor();
+ gm.y = gm.y.floor();
+ gm.xoff = gm.xoff.round();
+ gm.yoff = gm.yoff.round();
+ }
+
return gm;
}
QFixed QFontEngineMac::ascent() const
{
- return m_ascent;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_ascent.round()
+ : m_ascent;
}
QFixed QFontEngineMac::descent() const
{
// subtract a pixel to even out the historical +1 in QFontMetrics::height().
// Fix in Qt 5.
- return m_descent - 1;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_descent.round() - 1
+ : m_descent;
}
QFixed QFontEngineMac::leading() const
{
- return m_leading;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_leading.round()
+ : m_leading;
}
qreal QFontEngineMac::maxCharWidth() const
{
- return m_maxCharWidth;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? qRound(m_maxCharWidth)
+ : m_maxCharWidth;
}
QFixed QFontEngineMac::xHeight() const
{
- return m_xHeight;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_xHeight.round()
+ : m_xHeight;
}
QFixed QFontEngineMac::averageCharWidth() const
{
- return m_averageCharWidth;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_averageCharWidth.round()
+ : m_averageCharWidth;
}
static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path)
diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp
index 136737d..a0593cc 100644
--- a/src/gui/text/qfontengine_qpf.cpp
+++ b/src/gui/text/qfontengine_qpf.cpp
@@ -920,8 +920,18 @@ void QFontEngineQPF::loadGlyph(glyph_t glyph)
if (!renderingFontEngine)
return;
-
- QImage img = renderingFontEngine->alphaMapForGlyph(glyph).convertToFormat(QImage::Format_Indexed8);
+ QImage img = renderingFontEngine->alphaMapForGlyph(glyph);
+ if (img.format() != QImage::Format_Indexed8) {
+ bool mono = img.depth() == 1;
+ img = img.convertToFormat(QImage::Format_Indexed8);
+ if (mono) {
+ //### we know that 1 is opaque and 0 is transparent
+ uchar *byte = img.bits();
+ int count = img.byteCount();
+ while (count--)
+ *byte++ *= 0xff;
+ }
+ }
glyph_metrics_t metrics = renderingFontEngine->boundingBox(glyph);
renderingFontEngine->removeGlyphFromCache(glyph);
diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp
index eea196e..a805612 100644
--- a/src/gui/text/qfontengine_win.cpp
+++ b/src/gui/text/qfontengine_win.cpp
@@ -213,7 +213,7 @@ void QFontEngineWin::getCMap()
unitsPerEm = otm->otmEMSquare;
x_height = (int)otm->otmsXHeight;
loadKerningPairs(designToDevice);
- _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpFullName)).toLatin1();
+ _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFullName)).toLatin1();
lineWidth = otm->otmsUnderscoreSize;
fsType = otm->otmfsType;
free(otm);
@@ -1037,8 +1037,8 @@ QFontEngine::Properties QFontEngineWin::properties() const
Properties p;
p.emSquare = unitsPerEm;
p.italicAngle = otm->otmItalicAngle;
- p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpFamilyName)).toLatin1();
- p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpStyleName)).toLatin1();
+ p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFamilyName)).toLatin1();
+ p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpStyleName)).toLatin1();
#ifndef QT_NO_PRINTER
p.postscriptName = QPdf::stripSpecialCharacters(p.postscriptName);
#endif
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 44a18de..3a52e8e 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -328,7 +328,7 @@ int QFontMetrics::height() const
{
QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
Q_ASSERT(engine != 0);
- return qRound(engine->ascent() + engine->descent()) + 1;
+ return qRound(engine->ascent()) + qRound(engine->descent()) + 1;
}
/*!
@@ -356,7 +356,7 @@ int QFontMetrics::lineSpacing() const
{
QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
Q_ASSERT(engine != 0);
- return qRound(engine->leading() + engine->ascent() + engine->descent()) + 1;
+ return qRound(engine->leading()) + qRound(engine->ascent()) + qRound(engine->descent()) + 1;
}
/*!
@@ -535,7 +535,7 @@ int QFontMetrics::width(const QString &text, int len) const
if (len == 0)
return 0;
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
return qRound(layout.width(0, len));
}
@@ -611,7 +611,7 @@ int QFontMetrics::charWidth(const QString &text, int pos) const
int from = qMax(0, pos - 8);
int to = qMin(text.length(), pos + 8);
QString cstr = QString::fromRawData(text.unicode() + from, to - from);
- QTextEngine layout(cstr, d.data());
+ QStackTextEngine layout(cstr, d.data());
layout.ignoreBidi = true;
layout.itemize();
width = qRound(layout.width(pos-from, 1));
@@ -660,7 +660,7 @@ QRect QFontMetrics::boundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, text.length());
@@ -830,7 +830,7 @@ QRect QFontMetrics::tightBoundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
@@ -1375,7 +1375,7 @@ qreal QFontMetricsF::width(const QString &text) const
int pos = text.indexOf(QLatin1Char('\x9c'));
int len = (pos != -1) ? pos : text.length();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
return layout.width(0, len).toReal();
@@ -1452,7 +1452,7 @@ QRectF QFontMetricsF::boundingRect(const QString &text) const
if (len == 0)
return QRectF();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, len);
@@ -1625,7 +1625,7 @@ QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
new file mode 100644
index 0000000..5f31ef0
--- /dev/null
+++ b/src/gui/text/qstatictext.cpp
@@ -0,0 +1,654 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstatictext.h"
+#include "qstatictext_p.h"
+#include <private/qtextengine_p.h>
+#include <private/qfontengine_p.h>
+
+#include <QtGui/qapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QStaticText
+ \brief The QStaticText class enables optimized drawing of text when the text and its layout
+ is updated rarely.
+ \since 4.7
+
+ \ingroup multimedia
+ \ingroup text
+ \mainclass
+
+ QStaticText provides a way to cache layout data for a block of text so that it can be drawn
+ more efficiently than by using QPainter::drawText() in which the layout information is
+ recalculated with every call.
+
+ The class primarily provides an optimization for cases where the text, its font and the
+ transformations on the painter are static over several paint events. If the text or its layout
+ is changed for every iteration, QPainter::drawText() is the more efficient alternative, since
+ the static text's layout would have to be recalculated to take the new state into consideration.
+
+ Translating the painter will not cause the layout of the text to be recalculated, but will cause
+ a very small performance impact on drawStaticText(). Altering any other parts of the painter's
+ transformation or the painter's font will cause the layout of the static text to be
+ recalculated. This should be avoided as often as possible to maximize the performance
+ benefit of using QStaticText.
+
+ In addition, only affine transformations are supported by drawStaticText(). Calling
+ drawStaticText() on a projected painter will perform slightly worse than using the regular
+ drawText() call, so this should be avoided.
+
+ \code
+ class MyWidget: public QWidget
+ {
+ public:
+ MyWidget(QWidget *parent = 0) : QWidget(parent), m_staticText("This is static text")
+
+ protected:
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter painter(this);
+ painter.drawStaticText(0, 0, m_staticText);
+ }
+
+ private:
+ QStaticText m_staticText;
+ };
+ \endcode
+
+ The QStaticText class can be used to mimic the behavior of QPainter::drawText() to a specific
+ point with no boundaries, and also when QPainter::drawText() is called with a bounding
+ rectangle.
+
+ If a bounding rectangle is not required, create a QStaticText object without setting a preferred
+ text width. The text will then occupy a single line.
+
+ If you set a text width on the QStaticText object, this will bound the text. The text will
+ be formatted so that no line exceeds the given width. The text width set for QStaticText will
+ not automatically be used for clipping. To achieve clipping in addition to line breaks, use
+ QPainter::setClipRect(). The position of the text is decided by the argument passed to
+ QPainter::drawStaticText() and can change from call to call with a minimal impact on
+ performance.
+
+ QStaticText will attempt to guess the format of the input text using Qt::mightBeRichText().
+ To force QStaticText to display its contents as either plain text or rich text, use the
+ function QStaticText::setTextFormat() and pass in, respectively, Qt::PlainText and
+ Qt::RichText.
+
+ If it's the first time the static text is drawn, or if the static text, or the painter's font
+ or matrix have been altered since the last time it was drawn, the text's layout has to be
+ recalculated. This will impose an overhead on the QPainter::drawStaticText() call where the
+ relayout occurs. To avoid this overhead in the paint event, you can call prepare() ahead of
+ time to ensure that the layout is calculated.
+
+ \sa QPainter::drawText(), QPainter::drawStaticText(), QTextLayout, QTextDocument
+*/
+
+/*!
+ \enum QStaticText::PerformanceHint
+
+ This enum the different performance hints that can be set on the QStaticText. These hints
+ can be used to indicate that the QStaticText should use additional caches, if possible,
+ to improve performance at the expense of memory. In particular, setting the performance hint
+ AggressiveCaching on the QStaticText will improve performance when using the OpenGL graphics
+ system or when drawing to a QGLWidget.
+
+ \value ModerateCaching Do basic caching for high performance at a low memory cost.
+ \value AggressiveCaching Use additional caching when available. This may improve performance
+ at a higher memory cost.
+*/
+
+/*!
+ Constructs an empty QStaticText
+*/
+QStaticText::QStaticText()
+ : data(new QStaticTextPrivate)
+{
+}
+
+/*!
+ Constructs a QStaticText object with the given \a text and bounded by the given \a size.
+
+ If an invalid size is passed for \a size the text will be unbounded.
+*/
+QStaticText::QStaticText(const QString &text)
+ : data(new QStaticTextPrivate)
+{
+ data->text = text;
+ data->invalidate();
+}
+
+/*!
+ Constructs a QStaticText object which is a copy of \a other.
+*/
+QStaticText::QStaticText(const QStaticText &other)
+{
+ data = other.data;
+}
+
+/*!
+ Destroys the QStaticText.
+*/
+QStaticText::~QStaticText()
+{
+ Q_ASSERT(!data || data->ref >= 1);
+}
+
+/*!
+ \internal
+*/
+void QStaticText::detach()
+{
+ if (data->ref != 1)
+ data.detach();
+}
+
+/*!
+ Prepares the QStaticText object for being painted with the given \a matrix and the given \a font
+ to avoid overhead when the actual drawStaticText() call is made.
+
+ When drawStaticText() is called, the layout of the QStaticText will be recalculated if any part
+ of the QStaticText object has changed since the last time it was drawn. It will also be
+ recalculated if the painter's font or matrix are not the same as when the QStaticText was last
+ drawn.
+
+ To avoid the overhead of creating the layout the first time you draw the QStaticText after
+ making changes, you can use the prepare() function and pass in the \a matrix and \a font you
+ expect to use when drawing the text.
+
+ \sa QPainter::setFont(), QPainter::setMatrix()
+*/
+void QStaticText::prepare(const QTransform &matrix, const QFont &font)
+{
+ data->matrix = matrix;
+ data->font = font;
+ data->init();
+}
+
+
+/*!
+ Assigns \a other to this QStaticText.
+*/
+QStaticText &QStaticText::operator=(const QStaticText &other)
+{
+ data = other.data;
+ return *this;
+}
+
+/*!
+ Compares \a other to this QStaticText. Returns true if the texts, fonts and text widths
+ are equal.
+*/
+bool QStaticText::operator==(const QStaticText &other) const
+{
+ return (data == other.data
+ || (data->text == other.data->text
+ && data->font == other.data->font
+ && data->textWidth == other.data->textWidth));
+}
+
+/*!
+ Compares \a other to this QStaticText. Returns true if the texts, fonts or maximum sizes
+ are different.
+*/
+bool QStaticText::operator!=(const QStaticText &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ Sets the text of the QStaticText to \a text.
+
+ \note This function will cause the layout of the text to require recalculation.
+
+ \sa text()
+*/
+void QStaticText::setText(const QString &text)
+{
+ detach();
+ data->text = text;
+ data->invalidate();
+}
+
+/*!
+ Sets the text format of the QStaticText to \a textFormat. If \a textFormat is set to
+ Qt::AutoText (the default), the format of the text will try to be determined using the
+ function Qt::mightBeRichText(). If the text format is Qt::PlainText, then the text will be
+ displayed as is, whereas it will be interpreted as HTML if the format is Qt::RichText. HTML tags
+ that alter the font of the text, its color, or its layout are supported by QStaticText.
+
+ \note This function will cause the layout of the text to require recalculation.
+
+ \sa textFormat(), setText(), text()
+*/
+void QStaticText::setTextFormat(Qt::TextFormat textFormat)
+{
+ detach();
+ data->textFormat = textFormat;
+ data->invalidate();
+}
+
+/*!
+ Returns the text format of the QStaticText.
+
+ \sa setTextFormat(), setText(), text()
+*/
+Qt::TextFormat QStaticText::textFormat() const
+{
+ return Qt::TextFormat(data->textFormat);
+}
+
+/*!
+ Returns the text of the QStaticText.
+
+ \sa setText()
+*/
+QString QStaticText::text() const
+{
+ return data->text;
+}
+
+/*!
+ Sets the performance hint of the QStaticText according to the \a
+ performanceHint provided. The \a performanceHint is used to
+ customize how much caching is done internally to improve
+ performance.
+
+ The default is QStaticText::ModerateCaching.
+
+ \note This function will cause the layout of the text to require recalculation.
+
+ \sa performanceHint()
+*/
+void QStaticText::setPerformanceHint(PerformanceHint performanceHint)
+{
+ if ((performanceHint == ModerateCaching && !data->useBackendOptimizations)
+ || (performanceHint == AggressiveCaching && data->useBackendOptimizations)) {
+ return;
+ }
+ detach();
+ data->useBackendOptimizations = (performanceHint == AggressiveCaching);
+ data->invalidate();
+}
+
+/*!
+ Returns which performance hint is set for the QStaticText.
+
+ \sa setPerformanceHint()
+*/
+QStaticText::PerformanceHint QStaticText::performanceHint() const
+{
+ return data->useBackendOptimizations ? AggressiveCaching : ModerateCaching;
+}
+
+/*!
+ Sets the preferred width for this QStaticText. If the text is wider than the specified width,
+ it will be broken into multiple lines and grow vertically. If the text cannot be split into
+ multiple lines, it will be larger than the specified \a textWidth.
+
+ Setting the preferred text width to a negative number will cause the text to be unbounded.
+
+ Use size() to get the actual size of the text.
+
+ \note This function will cause the layout of the text to require recalculation.
+
+ \sa textWidth(), size()
+*/
+void QStaticText::setTextWidth(qreal textWidth)
+{
+ detach();
+ data->textWidth = textWidth;
+ data->invalidate();
+}
+
+/*!
+ Returns the preferred width for this QStaticText.
+
+ \sa setTextWidth()
+*/
+qreal QStaticText::textWidth() const
+{
+ return data->textWidth;
+}
+
+/*!
+ Returns the size of the bounding rect for this QStaticText.
+
+ \sa textWidth()
+*/
+QSizeF QStaticText::size() const
+{
+ if (data->needsRelayout)
+ data->init();
+ return data->actualSize;
+}
+
+QStaticTextPrivate::QStaticTextPrivate()
+ : items(0), itemCount(0), glyphPool(0), positionPool(0), textWidth(-1.0),
+ needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText)
+{
+}
+
+QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other)
+ : text(other.text), font(other.font), textWidth(other.textWidth), matrix(other.matrix),
+ items(0), itemCount(0), glyphPool(0), positionPool(0), needsRelayout(true),
+ useBackendOptimizations(other.useBackendOptimizations), textFormat(other.textFormat)
+{
+}
+
+QStaticTextPrivate::~QStaticTextPrivate()
+{
+ delete[] items;
+ delete[] glyphPool;
+ delete[] positionPool;
+}
+
+QStaticTextPrivate *QStaticTextPrivate::get(const QStaticText *q)
+{
+ return q->data.data();
+}
+
+extern int qt_defaultDpiX();
+extern int qt_defaultDpiY();
+
+namespace {
+
+ class DrawTextItemRecorder: public QPaintEngine
+ {
+ public:
+ DrawTextItemRecorder(int expectedItemCount, QStaticTextItem *items,
+ int expectedGlyphCount, QFixedPoint *positionPool, glyph_t *glyphPool)
+ : m_items(items),
+ m_itemCount(0), m_glyphCount(0),
+ m_expectedItemCount(expectedItemCount),
+ m_expectedGlyphCount(expectedGlyphCount),
+ m_glyphPool(glyphPool),
+ m_positionPool(positionPool),
+ m_dirtyPen(false)
+ {
+ }
+
+ virtual void updateState(const QPaintEngineState &newState)
+ {
+ if (newState.state() & QPaintEngine::DirtyPen)
+ m_dirtyPen = true;
+ }
+
+ virtual void drawTextItem(const QPointF &position, const QTextItem &textItem)
+ {
+ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+
+ m_itemCount++;
+ m_glyphCount += ti.glyphs.numGlyphs;
+ if (m_items == 0)
+ return;
+
+ Q_ASSERT(m_itemCount <= m_expectedItemCount);
+ Q_ASSERT(m_glyphCount <= m_expectedGlyphCount);
+
+ QStaticTextItem *currentItem = (m_items + (m_itemCount - 1));
+ currentItem->fontEngine = ti.fontEngine;
+ currentItem->font = ti.font();
+ currentItem->chars = ti.chars;
+ currentItem->numChars = ti.num_chars;
+ currentItem->numGlyphs = ti.glyphs.numGlyphs;
+ currentItem->glyphs = m_glyphPool;
+ currentItem->glyphPositions = m_positionPool;
+ if (m_dirtyPen)
+ currentItem->color = state->pen().color();
+
+ QTransform matrix = state->transform();
+ matrix.translate(position.x(), position.y());
+
+ QVarLengthArray<glyph_t> glyphs;
+ QVarLengthArray<QFixedPoint> positions;
+ ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
+
+ int size = glyphs.size();
+ Q_ASSERT(size == ti.glyphs.numGlyphs);
+ Q_ASSERT(size == positions.size());
+
+ memmove(currentItem->glyphs, glyphs.constData(), sizeof(glyph_t) * size);
+ memmove(currentItem->glyphPositions, positions.constData(), sizeof(QFixedPoint) * size);
+
+ m_glyphPool += size;
+ m_positionPool += size;
+ }
+
+
+ virtual bool begin(QPaintDevice *) { return true; }
+ virtual bool end() { return true; }
+ virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {}
+ virtual Type type() const
+ {
+ return User;
+ }
+
+ int itemCount() const
+ {
+ return m_itemCount;
+ }
+
+ int glyphCount() const
+ {
+ return m_glyphCount;
+ }
+
+ private:
+ QStaticTextItem *m_items;
+ int m_itemCount;
+ int m_glyphCount;
+ int m_expectedItemCount;
+ int m_expectedGlyphCount;
+
+ glyph_t *m_glyphPool;
+ QFixedPoint *m_positionPool;
+
+ bool m_dirtyPen;
+ };
+
+ class DrawTextItemDevice: public QPaintDevice
+ {
+ public:
+ DrawTextItemDevice(int expectedItemCount = -1, QStaticTextItem *items = 0,
+ int expectedGlyphCount = -1, QFixedPoint *positionPool = 0,
+ glyph_t *glyphPool = 0)
+ {
+ m_paintEngine = new DrawTextItemRecorder(expectedItemCount, items,
+ expectedGlyphCount, positionPool, glyphPool);
+ }
+
+ ~DrawTextItemDevice()
+ {
+ delete m_paintEngine;
+ }
+
+ int metric(PaintDeviceMetric m) const
+ {
+ int val;
+ switch (m) {
+ case PdmWidth:
+ case PdmHeight:
+ case PdmWidthMM:
+ case PdmHeightMM:
+ val = 0;
+ break;
+ case PdmDpiX:
+ case PdmPhysicalDpiX:
+ val = qt_defaultDpiX();
+ break;
+ case PdmDpiY:
+ case PdmPhysicalDpiY:
+ val = qt_defaultDpiY();
+ break;
+ case PdmNumColors:
+ val = 16777216;
+ break;
+ case PdmDepth:
+ val = 24;
+ break;
+ default:
+ val = 0;
+ qWarning("DrawTextItemDevice::metric: Invalid metric command");
+ }
+ return val;
+ }
+
+ virtual QPaintEngine *paintEngine() const
+ {
+ return m_paintEngine;
+ }
+
+ int itemCount() const
+ {
+ return m_paintEngine->itemCount();
+ }
+
+ int glyphCount() const
+ {
+ return m_paintEngine->glyphCount();
+ }
+
+ private:
+ DrawTextItemRecorder *m_paintEngine;
+ };
+}
+
+void QStaticTextPrivate::paintText(const QPointF &topLeftPosition, QPainter *p)
+{
+ bool preferRichText = textFormat == Qt::RichText
+ || (textFormat == Qt::AutoText && Qt::mightBeRichText(text));
+
+ if (!preferRichText) {
+ QTextLayout textLayout;
+ textLayout.setText(text);
+ textLayout.setFont(font);
+
+ qreal leading = QFontMetricsF(font).leading();
+ qreal height = -leading;
+
+ textLayout.beginLayout();
+ while (1) {
+ QTextLine line = textLayout.createLine();
+ if (!line.isValid())
+ break;
+
+ if (textWidth >= 0.0)
+ line.setLineWidth(textWidth);
+ height += leading;
+ line.setPosition(QPointF(0.0, height));
+ height += line.height();
+ }
+ textLayout.endLayout();
+
+ actualSize = textLayout.boundingRect().size();
+ textLayout.draw(p, topLeftPosition);
+ } else {
+ QTextDocument document;
+ QColor color = p->pen().color();
+ document.setDefaultStyleSheet(QString::fromLatin1("body { color: #%1%2%3 }")
+ .arg(QString::number(color.red(), 16), 2, QLatin1Char('0'))
+ .arg(QString::number(color.green(), 16), 2, QLatin1Char('0'))
+ .arg(QString::number(color.blue(), 16), 2, QLatin1Char('0')));
+ document.setDefaultFont(font);
+ document.setDocumentMargin(0.0);
+ if (textWidth >= 0.0)
+ document.setTextWidth(textWidth);
+ document.setHtml(text);
+
+ document.adjustSize();
+ p->save();
+ p->translate(topLeftPosition);
+ document.drawContents(p);
+ p->restore();
+
+ actualSize = document.size();
+ }
+}
+
+void QStaticTextPrivate::init()
+{
+ delete[] items;
+ delete[] glyphPool;
+ delete[] positionPool;
+
+ position = QPointF(0, 0);
+
+ // Draw once to count number of items and glyphs, so that we can use as little memory
+ // as possible to store the data
+ DrawTextItemDevice counterDevice;
+ {
+ QPainter painter(&counterDevice);
+ painter.setFont(font);
+ painter.setTransform(matrix);
+
+ paintText(QPointF(0, 0), &painter);
+
+ }
+
+ itemCount = counterDevice.itemCount();
+ items = new QStaticTextItem[itemCount];
+
+ if (useBackendOptimizations) {
+ for (int i=0; i<itemCount; ++i)
+ items[i].useBackendOptimizations = true;
+ }
+
+
+ int glyphCount = counterDevice.glyphCount();
+ glyphPool = new glyph_t[glyphCount];
+ positionPool = new QFixedPoint[glyphCount];
+
+ // Draw again to actually record the items and glyphs
+ DrawTextItemDevice recorderDevice(itemCount, items, glyphCount, positionPool, glyphPool);
+ {
+ QPainter painter(&recorderDevice);
+ painter.setFont(font);
+ painter.setTransform(matrix);
+
+ paintText(QPointF(0, 0), &painter);
+ }
+
+ needsRelayout = false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h
new file mode 100644
index 0000000..f3bef93
--- /dev/null
+++ b/src/gui/text/qstatictext.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATICTEXT_H
+#define QSTATICTEXT_H
+
+#include <QtCore/qsize.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qmetatype.h>
+
+#include <QtGui/qtransform.h>
+#include <QtGui/qfont.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QStaticTextPrivate;
+class Q_GUI_EXPORT QStaticText
+{
+public:
+ enum PerformanceHint {
+ ModerateCaching,
+ AggressiveCaching
+ };
+
+ QStaticText();
+ QStaticText(const QString &text);
+ QStaticText(const QStaticText &other);
+ ~QStaticText();
+
+ void setText(const QString &text);
+ QString text() const;
+
+ void setTextFormat(Qt::TextFormat textFormat);
+ Qt::TextFormat textFormat() const;
+
+ void setTextWidth(qreal textWidth);
+ qreal textWidth() const;
+
+ QSizeF size() const;
+
+ void prepare(const QTransform &matrix = QTransform(), const QFont &font = QFont());
+
+ void setPerformanceHint(PerformanceHint performanceHint);
+ PerformanceHint performanceHint() const;
+
+ QStaticText &operator=(const QStaticText &);
+ bool operator==(const QStaticText &) const;
+ bool operator!=(const QStaticText &) const;
+
+private:
+ void detach();
+
+ QExplicitlySharedDataPointer<QStaticTextPrivate> data;
+ friend class QStaticTextPrivate;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QStaticText)
+
+QT_END_HEADER
+
+#endif // QSTATICTEXT_H
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
new file mode 100644
index 0000000..f017ed1
--- /dev/null
+++ b/src/gui/text/qstatictext_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATICTEXT_P_H
+#define QSTATICTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of internal files. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qtextureglyphcache_p.h>
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_NAMESPACE
+
+class QStaticTextUserData
+{
+public:
+ enum Type {
+ NoUserData,
+ OpenGLUserData
+ };
+
+ QStaticTextUserData(Type t) : type(t) {}
+ virtual ~QStaticTextUserData() {}
+
+ Type type;
+};
+
+class Q_GUI_EXPORT QStaticTextItem
+{
+public:
+ QStaticTextItem() : chars(0), numChars(0), fontEngine(0), userData(0),
+ useBackendOptimizations(false), userDataNeedsUpdate(0) {}
+ ~QStaticTextItem() { delete userData; }
+
+ void setUserData(QStaticTextUserData *newUserData)
+ {
+ if (userData == newUserData)
+ return;
+
+ delete userData;
+ userData = newUserData;
+ }
+
+ QFixedPoint *glyphPositions; // 8 bytes per glyph
+ glyph_t *glyphs; // 4 bytes per glyph
+ const QChar *chars; // 2 bytes per glyph
+ // =================
+ // 14 bytes per glyph
+
+ // 12 bytes for pointers
+ int numGlyphs; // 4 bytes per item
+ int numChars; // 4 bytes per item
+ QFontEngine *fontEngine; // 4 bytes per item
+ QFont font; // 8 bytes per item
+ QColor color; // 10 bytes per item
+ QStaticTextUserData *userData; // 8 bytes per item
+ char useBackendOptimizations : 1; // 1 byte per item
+ char userDataNeedsUpdate : 1; //
+ // ================
+ // 51 bytes per item
+};
+
+class QStaticText;
+class Q_AUTOTEST_EXPORT QStaticTextPrivate
+{
+public:
+ QStaticTextPrivate();
+ QStaticTextPrivate(const QStaticTextPrivate &other);
+ ~QStaticTextPrivate();
+
+ void init();
+ void paintText(const QPointF &pos, QPainter *p);
+
+ void invalidate()
+ {
+ needsRelayout = true;
+ }
+
+ QAtomicInt ref; // 4 bytes per text
+
+ QString text; // 4 bytes per text
+ QFont font; // 8 bytes per text
+ qreal textWidth; // 8 bytes per text
+ QSizeF actualSize; // 16 bytes per text
+ QPointF position; // 16 bytes per text
+
+ QTransform matrix; // 80 bytes per text
+ QStaticTextItem *items; // 4 bytes per text
+ int itemCount; // 4 bytes per text
+ glyph_t *glyphPool; // 4 bytes per text
+ QFixedPoint *positionPool; // 4 bytes per text
+
+ unsigned char needsRelayout : 1;
+ unsigned char useBackendOptimizations : 1; // 1 byte per text
+ unsigned char textFormat : 2;
+ // ================
+ // 163 bytes per text
+
+ static QStaticTextPrivate *get(const QStaticText *q);
+};
+
+QT_END_NAMESPACE
+
+#endif // QSTATICTEXT_P_H
diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp
index 6750c09..e594b7e 100644
--- a/src/gui/text/qsyntaxhighlighter.cpp
+++ b/src/gui/text/qsyntaxhighlighter.cpp
@@ -59,23 +59,24 @@ class QSyntaxHighlighterPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QSyntaxHighlighter)
public:
- inline QSyntaxHighlighterPrivate() : rehighlightPending(false) {}
+ inline QSyntaxHighlighterPrivate()
+ : rehighlightPending(false), inReformatBlocks(false)
+ {}
QPointer<QTextDocument> doc;
void _q_reformatBlocks(int from, int charsRemoved, int charsAdded);
- void reformatBlock(QTextBlock block);
-
+ void reformatBlocks(int from, int charsRemoved, int charsAdded);
+ void reformatBlock(const QTextBlock &block);
+
inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation) {
- QObject::disconnect(doc, SIGNAL(contentsChange(int,int,int)),
- q_func(), SLOT(_q_reformatBlocks(int,int,int)));
+ inReformatBlocks = true;
cursor.beginEditBlock();
int from = cursor.position();
cursor.movePosition(operation);
- _q_reformatBlocks(from, 0, cursor.position() - from);
+ reformatBlocks(from, 0, cursor.position() - from);
cursor.endEditBlock();
- QObject::connect(doc, SIGNAL(contentsChange(int,int,int)),
- q_func(), SLOT(_q_reformatBlocks(int,int,int)));
+ inReformatBlocks = false;
}
inline void _q_delayedRehighlight() {
@@ -83,17 +84,19 @@ public:
return;
rehighlightPending = false;
q_func()->rehighlight();
- return;
}
void applyFormatChanges();
QVector<QTextCharFormat> formatChanges;
QTextBlock currentBlock;
bool rehighlightPending;
+ bool inReformatBlocks;
};
void QSyntaxHighlighterPrivate::applyFormatChanges()
{
+ bool formatsChanged = false;
+
QTextLayout *layout = currentBlock.layout();
QList<QTextLayout::FormatRange> ranges = layout->additionalFormats();
@@ -101,19 +104,26 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
const int preeditAreaStart = layout->preeditAreaPosition();
const int preeditAreaLength = layout->preeditAreaText().length();
- QList<QTextLayout::FormatRange>::Iterator it = ranges.begin();
- while (it != ranges.end()) {
- if (it->start >= preeditAreaStart
- && it->start + it->length <= preeditAreaStart + preeditAreaLength)
- ++it;
- else
- it = ranges.erase(it);
+ if (preeditAreaLength != 0) {
+ QList<QTextLayout::FormatRange>::Iterator it = ranges.begin();
+ while (it != ranges.end()) {
+ if (it->start >= preeditAreaStart
+ && it->start + it->length <= preeditAreaStart + preeditAreaLength) {
+ ++it;
+ } else {
+ it = ranges.erase(it);
+ formatsChanged = true;
+ }
+ }
+ } else if (!ranges.isEmpty()) {
+ ranges.clear();
+ formatsChanged = true;
}
QTextCharFormat emptyFormat;
QTextLayout::FormatRange r;
- r.start = r.length = -1;
+ r.start = -1;
int i = 0;
while (i < formatChanges.count()) {
@@ -135,34 +145,46 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
r.length = i - r.start;
- if (r.start >= preeditAreaStart) {
- r.start += preeditAreaLength;
- } else if (r.start + r.length >= preeditAreaStart) {
- r.length += preeditAreaLength;
+ if (preeditAreaLength != 0) {
+ if (r.start >= preeditAreaStart)
+ r.start += preeditAreaLength;
+ else if (r.start + r.length >= preeditAreaStart)
+ r.length += preeditAreaLength;
}
ranges << r;
- r.start = r.length = -1;
+ formatsChanged = true;
+ r.start = -1;
}
if (r.start != -1) {
r.length = formatChanges.count() - r.start;
- if (r.start >= preeditAreaStart) {
- r.start += preeditAreaLength;
- } else if (r.start + r.length >= preeditAreaStart) {
- r.length += preeditAreaLength;
+ if (preeditAreaLength != 0) {
+ if (r.start >= preeditAreaStart)
+ r.start += preeditAreaLength;
+ else if (r.start + r.length >= preeditAreaStart)
+ r.length += preeditAreaLength;
}
ranges << r;
+ formatsChanged = true;
}
- layout->setAdditionalFormats(ranges);
+ if (formatsChanged) {
+ layout->setAdditionalFormats(ranges);
+ doc->markContentsDirty(currentBlock.position(), currentBlock.length());
+ }
}
void QSyntaxHighlighterPrivate::_q_reformatBlocks(int from, int charsRemoved, int charsAdded)
{
- Q_UNUSED(charsRemoved);
+ if (!inReformatBlocks)
+ reformatBlocks(from, charsRemoved, charsAdded);
+}
+
+void QSyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded)
+{
rehighlightPending = false;
QTextBlock block = doc->findBlock(from);
@@ -191,21 +213,18 @@ void QSyntaxHighlighterPrivate::_q_reformatBlocks(int from, int charsRemoved, in
formatChanges.clear();
}
-void QSyntaxHighlighterPrivate::reformatBlock(QTextBlock block)
+void QSyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block)
{
Q_Q(QSyntaxHighlighter);
Q_ASSERT_X(!currentBlock.isValid(), "QSyntaxHighlighter::reformatBlock()", "reFormatBlock() called recursively");
currentBlock = block;
- QTextBlock previous = block.previous();
formatChanges.fill(QTextCharFormat(), block.length() - 1);
q->highlightBlock(block.text());
applyFormatChanges();
- doc->markContentsDirty(block.position(), block.length());
-
currentBlock = QTextBlock();
}
@@ -349,8 +368,8 @@ void QSyntaxHighlighter::setDocument(QTextDocument *doc)
if (d->doc) {
connect(d->doc, SIGNAL(contentsChange(int,int,int)),
this, SLOT(_q_reformatBlocks(int,int,int)));
- QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight()));
d->rehighlightPending = true;
+ QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight()));
}
}
@@ -391,11 +410,16 @@ void QSyntaxHighlighter::rehighlight()
void QSyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
{
Q_D(QSyntaxHighlighter);
- if (!d->doc)
+ if (!d->doc || !block.isValid() || block.document() != d->doc)
return;
+ const bool rehighlightPending = d->rehighlightPending;
+
QTextCursor cursor(block);
d->rehighlight(cursor, QTextCursor::EndOfBlock);
+
+ if (rehighlightPending)
+ d->rehighlightPending = rehighlightPending;
}
/*!
@@ -460,7 +484,6 @@ void QSyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
void QSyntaxHighlighter::setFormat(int start, int count, const QTextCharFormat &format)
{
Q_D(QSyntaxHighlighter);
-
if (start < 0 || start >= d->formatChanges.count())
return;
@@ -628,7 +651,7 @@ QTextBlockUserData *QSyntaxHighlighter::currentBlockUserData() const
\since 4.4
Returns the current text block.
- */
+*/
QTextBlock QSyntaxHighlighter::currentBlock() const
{
Q_D(const QSyntaxHighlighter);
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index aaaa3ca..6864fe1 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -441,7 +441,6 @@ void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text,
QObject::connect(doc, SIGNAL(documentLayoutChanged()), q, SLOT(_q_documentLayoutChanged()));
// convenience signal forwards
- QObject::connect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));
QObject::connect(doc, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool)));
QObject::connect(doc, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool)));
QObject::connect(doc, SIGNAL(modificationChanged(bool)), q, SIGNAL(modificationChanged(bool)));
@@ -452,8 +451,11 @@ void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text,
if (!document)
doc->setUndoRedoEnabled(false);
+ //Saving the index save some time.
+ static int contentsChangedIndex = QTextDocument::staticMetaObject.indexOfSignal("contentsChanged()");
+ static int textChangedIndex = QTextControl::staticMetaObject.indexOfSignal("textChanged()");
// avoid multiple textChanged() signals being emitted
- QObject::disconnect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));
+ QMetaObject::disconnect(doc, contentsChangedIndex, q, textChangedIndex);
if (!text.isEmpty()) {
// clear 'our' cursor for insertion to prevent
@@ -488,7 +490,7 @@ void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text,
}
cursor.setCharFormat(charFormatForInsertion);
- QObject::connect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));
+ QMetaObject::connect(doc, contentsChangedIndex, q, textChangedIndex);
emit q->textChanged();
if (!document)
doc->setUndoRedoEnabled(previousUndoRedoState);
@@ -846,9 +848,9 @@ void QTextControl::copy()
QApplication::clipboard()->setMimeData(data);
}
-void QTextControl::paste()
+void QTextControl::paste(QClipboard::Mode mode)
{
- const QMimeData *md = QApplication::clipboard()->mimeData();
+ const QMimeData *md = QApplication::clipboard()->mimeData(mode);
if (md)
insertFromMimeData(md);
}
@@ -1228,7 +1230,12 @@ void QTextControlPrivate::keyPressEvent(QKeyEvent *e)
q->cut();
}
else if (e == QKeySequence::Paste) {
- q->paste();
+ QClipboard::Mode mode = QClipboard::Clipboard;
+#ifdef Q_WS_X11
+ if (e->modifiers() == (Qt::CTRL | Qt::SHIFT) && e->key() == Qt::Key_Insert)
+ mode = QClipboard::Selection;
+#endif
+ q->paste(mode);
}
#endif
else if (e == QKeySequence::Delete) {
@@ -1762,8 +1769,8 @@ void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPoint
QMenu *menu = q->createStandardContextMenu(docPos, contextWidget);
if (!menu)
return;
- menu->exec(screenPos);
- delete menu;
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(screenPos);
#endif
}
diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h
index 40507f4..8399d50 100644
--- a/src/gui/text/qtextcontrol_p.h
+++ b/src/gui/text/qtextcontrol_p.h
@@ -62,6 +62,7 @@
#include <QtCore/qrect.h>
#include <QtGui/qabstracttextdocumentlayout.h>
#include <QtGui/qtextdocumentfragment.h>
+#include <QtGui/qclipboard.h>
#ifdef QT3_SUPPORT
#include <QtGui/qtextobject.h>
@@ -191,7 +192,7 @@ public Q_SLOTS:
#ifndef QT_NO_CLIPBOARD
void cut();
void copy();
- void paste();
+ void paste(QClipboard::Mode mode = QClipboard::Clipboard);
#endif
void undo();
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index c81d538..c91df3c 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -1145,7 +1145,7 @@ void QTextCursor::setPosition(int pos, MoveMode m)
Returns the absolute position of the cursor within the document.
The cursor is positioned between characters.
- \sa setPosition() movePosition() anchor()
+ \sa setPosition() movePosition() anchor() positionInBlock()
*/
int QTextCursor::position() const
{
@@ -1155,6 +1155,22 @@ int QTextCursor::position() const
}
/*!
+ \since 4.7
+ Returns the relative position of the cursor within the block.
+ The cursor is positioned between characters.
+
+ This is equivalent to \c{ position() - block().position()}.
+
+ \sa position()
+*/
+int QTextCursor::positionInBlock() const
+{
+ if (!d || !d->priv)
+ return 0;
+ return d->position - d->block().position();
+}
+
+/*!
Returns the anchor position; this is the same as position() unless
there is a selection in which case position() marks one end of the
selection and anchor() marks the other end. Just like the cursor
@@ -2414,9 +2430,17 @@ int QTextCursor::blockNumber() const
return d->block().blockNumber();
}
+
/*!
\since 4.2
Returns the position of the cursor within its containing line.
+
+ Note that this is the column number relative to a wrapped line,
+ not relative to the block (i.e. the paragraph).
+
+ You probably want to call positionInBlock() instead.
+
+ \sa positionInBlock()
*/
int QTextCursor::columnNumber() const
{
diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h
index 38bc39d..3e968a3 100644
--- a/src/gui/text/qtextcursor.h
+++ b/src/gui/text/qtextcursor.h
@@ -89,6 +89,7 @@ public:
void setPosition(int pos, MoveMode mode = MoveAnchor);
int position() const;
+ int positionInBlock() const;
int anchor() const;
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 21f3189..9a1b70c 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -61,6 +61,7 @@
#include <qapplication.h>
#include "qtextcontrol_p.h"
#include "private/qtextedit_p.h"
+#include "private/qdataurl_p.h"
#include "qtextdocument_p.h"
#include <private/qprinter_p.h>
@@ -434,6 +435,30 @@ void QTextDocument::redo(QTextCursor *cursor)
}
}
+/*! \enum QTextDocument::Stacks
+
+ \value UndoStack The undo stack.
+ \value RedoStack The redo stack.
+ \value UndoAndRedoStacks Both the undo and redo stacks.
+*/
+
+/*!
+ \since 4.7
+ Clears the stacks specified by \a stacksToClear.
+
+ This method clears any commands on the undo stack, the redo stack,
+ or both (the default). If commands are cleared, the appropriate
+ signals are emitted, QTextDocument::undoAvailable() or
+ QTextDocument::redoAvailable().
+
+ \sa QTextDocument::undoAvailable() QTextDocument::redoAvailable()
+*/
+void QTextDocument::clearUndoRedoStacks(Stacks stacksToClear)
+{
+ Q_D(QTextDocument);
+ d->clearUndoRedoStacks(stacksToClear, true);
+}
+
/*!
\overload
@@ -1749,9 +1774,9 @@ void QTextDocument::print(QPrinter *printer) const
int pageCopies;
if (printer->collateCopies() == true){
docCopies = 1;
- pageCopies = printer->numCopies();
+ pageCopies = printer->supportsMultipleCopies() ? 1 : printer->copyCount();
} else {
- docCopies = printer->numCopies();
+ docCopies = printer->supportsMultipleCopies() ? 1 : printer->copyCount();
pageCopies = 1;
}
@@ -1924,6 +1949,10 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name)
}
#endif
+ // handle data: URLs
+ if (r.isNull() && name.scheme() == QLatin1String("data"))
+ r = qDecodeDataUrl(name).second;
+
// if resource was not loaded try to load it here
if (!doc && r.isNull() && name.isRelative()) {
QUrl currentURL = d->url;
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index b5bcb41..0140772 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -256,6 +256,13 @@ public:
void undo(QTextCursor *cursor);
void redo(QTextCursor *cursor);
+ enum Stacks {
+ UndoStack = 0x01,
+ RedoStack = 0x02,
+ UndoAndRedoStacks = UndoStack | RedoStack
+ };
+ void clearUndoRedoStacks(Stacks historyToClear = UndoAndRedoStacks);
+
int maximumBlockCount() const;
void setMaximumBlockCount(int maximum);
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 372b9dc..302a349 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
// The VxWorks DIAB compiler crashes when initializing the anonymouse union with { a7 }
#if !defined(Q_CC_DIAB)
# define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
- QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6, { a7 }, a8 }
+ QTextUndoCommand c = { a1, a2, 0, 0, quint8(a3), a4, a5, a6, { a7 }, a8 }
#else
# define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6 }; c.blockFormat = a7; c.revision = a8
@@ -259,8 +259,7 @@ void QTextDocumentPrivate::clear()
objects.clear();
title.clear();
- undoState = 0;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::UndoAndRedoStacks);
text = QString();
unreachableCharacterCount = 0;
modifiedState = 0;
@@ -292,7 +291,7 @@ QTextDocumentPrivate::~QTextDocumentPrivate()
cursors.clear();
undoState = 0;
undoEnabled = true;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
}
void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout)
@@ -1027,7 +1026,7 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
if (!undoEnabled)
return;
if (undoState < undoStack.size())
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
if (!undoStack.isEmpty() && modified) {
QTextUndoCommand &last = undoStack[undoState - 1];
@@ -1050,26 +1049,46 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
emit document()->undoCommandAdded();
}
-void QTextDocumentPrivate::truncateUndoStack()
+void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToClear,
+ bool emitSignals)
{
- if (undoState == undoStack.size())
- return;
-
- for (int i = undoState; i < undoStack.size(); ++i) {
- QTextUndoCommand c = undoStack[i];
- if (c.command & QTextUndoCommand::Removed) {
- // ########
-// QTextFragment *f = c.fragment_list;
-// while (f) {
-// QTextFragment *n = f->right;
-// delete f;
-// f = n;
-// }
- } else if (c.command & QTextUndoCommand::Custom) {
- delete c.custom;
+ bool undoCommandsAvailable = undoState != 0;
+ bool redoCommandsAvailable = undoState != undoStack.size();
+ if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) {
+ for (int i = 0; i < undoState; ++i) {
+ QTextUndoCommand c = undoStack[undoState];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
}
+ undoStack.remove(0, undoState);
+ undoStack.resize(undoStack.size() - undoState);
+ undoState = 0;
+ if (emitSignals)
+ emitUndoAvailable(false);
+ } else if (stacksToClear == QTextDocument::RedoStack
+ && redoCommandsAvailable) {
+ for (int i = undoState; i < undoStack.size(); ++i) {
+ QTextUndoCommand c = undoStack[i];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
+ }
+ undoStack.resize(undoState);
+ if (emitSignals)
+ emitRedoAvailable(false);
+ } else if (stacksToClear == QTextDocument::UndoAndRedoStacks
+ && !undoStack.isEmpty()) {
+ for (int i = 0; i < undoStack.size(); ++i) {
+ QTextUndoCommand c = undoStack[i];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
+ }
+ undoState = 0;
+ undoStack.resize(0);
+ if (emitSignals && undoCommandsAvailable)
+ emitUndoAvailable(false);
+ if (emitSignals && redoCommandsAvailable)
+ emitRedoAvailable(false);
}
- undoStack.resize(undoState);
}
void QTextDocumentPrivate::emitUndoAvailable(bool available)
@@ -1097,7 +1116,7 @@ void QTextDocumentPrivate::enableUndoRedo(bool enable)
if (!enable) {
undoState = 0;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
emitUndoAvailable(false);
emitRedoAvailable(false);
}
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index 4ecc2fa..ac5ed3c 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -252,10 +252,11 @@ public:
inline QFont defaultFont() const { return formats.defaultFont(); }
inline void setDefaultFont(const QFont &f) { formats.setDefaultFont(f); }
+ void clearUndoRedoStacks(QTextDocument::Stacks stacksToClear, bool emitSignals = false);
+
private:
bool split(int pos);
bool unite(uint f);
- void truncateUndoStack();
void insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op);
int insert_block(int pos, uint strPos, int format, int blockformat, QTextUndoCommand::Operation op, int command);
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index b826588..7dc2c26 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1124,14 +1124,13 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
bool kerningEnabled = this->font(si).d->kerning;
HB_ShaperItem entire_shaper_item;
- entire_shaper_item.kerning_applied = false;
+ qMemSet(&entire_shaper_item, 0, sizeof(entire_shaper_item));
entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(layoutData->string.constData());
entire_shaper_item.stringLength = layoutData->string.length();
entire_shaper_item.item.script = (HB_Script)si.analysis.script;
entire_shaper_item.item.pos = si.position;
entire_shaper_item.item.length = length(item);
entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel;
- entire_shaper_item.glyphIndicesPresent = false;
HB_UChar16 upperCased[256]; // XXX what about making this 4096, so we don't have to extend it ever.
if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase
@@ -1299,10 +1298,10 @@ QTextEngine::QTextEngine()
}
QTextEngine::QTextEngine(const QString &str, const QFont &f)
- : fnt(f)
+ : text(str),
+ fnt(f)
{
init(this);
- text = str;
}
QTextEngine::~QTextEngine()
@@ -2467,7 +2466,7 @@ void QTextEngine::splitItem(int item, int pos) const
if (pos <= 0)
return;
- layoutData->items.insert(item + 1, QScriptItem(layoutData->items[item]));
+ layoutData->items.insert(item + 1, layoutData->items[item]);
QScriptItem &oldItem = layoutData->items[item];
QScriptItem &newItem = layoutData->items[item+1];
newItem.position += pos;
@@ -2610,10 +2609,9 @@ void QTextEngine::resolveAdditionalFormats() const
}
QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f)
- : _layoutData(string, _memory, MemSize)
+ : QTextEngine(string, f),
+ _layoutData(string, _memory, MemSize)
{
- fnt = f;
- text = string;
stackEngine = true;
layoutData = &_layoutData;
}
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index f36cbd2..5054b66 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -382,6 +382,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine
QFixed y;
QFixed width;
QFixed textWidth;
+ QFixed textAdvance;
int from;
signed int length : 29;
mutable uint justified : 1;
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 3c0e85e..312d135 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1570,6 +1570,20 @@ qreal QTextLine::naturalTextWidth() const
return eng->lines[i].textWidth.toReal();
}
+/*! \since 4.7
+ Returns the horizontal advance of the text. The advance of the text
+ is the distance from its position to the next position at which
+ text would naturally be drawn.
+
+ By adding the advance to the position of the text line and using this
+ as the position of a second text line, you will be able to position
+ the two lines side-by-side without gaps in-between.
+*/
+qreal QTextLine::horizontalAdvance() const
+{
+ return eng->lines[i].textAdvance.toReal();
+}
+
/*!
Lays out the line with the given \a width. The line is filled from
its starting position with as many characters as will fit into
@@ -1928,6 +1942,7 @@ void QTextLine::layout_helper(int maxGlyphs)
found:
if (lbh.rightBearing > 0) // If right bearing has not yet been adjusted
lbh.adjustRightBearing();
+ line.textAdvance = line.textWidth;
line.textWidth -= qMin(QFixed(), lbh.rightBearing);
if (line.length == 0) {
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index edae7de..8c93ed6 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -202,6 +202,7 @@ public:
bool leadingIncluded() const;
qreal naturalTextWidth() const;
+ qreal horizontalAdvance() const;
QRectF naturalTextRect() const;
enum Edge {
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index d30c996..6f099a9 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -280,6 +280,21 @@ static QFile::Permissions modeToPermissions(quint32 mode)
return ret;
}
+static QDateTime readMSDosDate(const uchar *src)
+{
+ uint dosDate = readUInt(src);
+ quint64 uDate;
+ uDate = (quint64)(dosDate >> 16);
+ uint tm_mday = (uDate & 0x1f);
+ uint tm_mon = ((uDate & 0x1E0) >> 5);
+ uint tm_year = (((uDate & 0x0FE00) >> 9) + 1980);
+ uint tm_hour = ((dosDate & 0xF800) >> 11);
+ uint tm_min = ((dosDate & 0x7E0) >> 5);
+ uint tm_sec = ((dosDate & 0x1f) << 1);
+
+ return QDateTime(QDate(tm_year, tm_mon, tm_mday), QTime(tm_hour, tm_min, tm_sec));
+}
+
struct LocalFileHeader
{
uchar signature[4]; // 0x04034b50
@@ -343,7 +358,7 @@ struct FileHeader
};
QZipReader::FileInfo::FileInfo()
- : isDir(false), isFile(true), isSymLink(false), crc32(0), size(0)
+ : isDir(false), isFile(false), isSymLink(false), crc32(0), size(0)
{
}
@@ -365,9 +380,15 @@ QZipReader::FileInfo& QZipReader::FileInfo::operator=(const FileInfo &other)
permissions = other.permissions;
crc32 = other.crc32;
size = other.size;
+ lastModified = other.lastModified;
return *this;
}
+bool QZipReader::FileInfo::isValid() const
+{
+ return isDir || isFile || isSymLink;
+}
+
class QZipPrivate
{
public:
@@ -403,6 +424,7 @@ void QZipPrivate::fillFileInfo(int index, QZipReader::FileInfo &fileInfo) const
fileInfo.permissions = modeToPermissions(mode);
fileInfo.crc32 = readUInt(header.h.crc_32);
fileInfo.size = readUInt(header.h.uncompressed_size);
+ fileInfo.lastModified = readMSDosDate(header.h.last_mod_file);
}
class QZipReaderPrivate : public QZipPrivate
@@ -750,6 +772,14 @@ QZipReader::~QZipReader()
}
/*!
+ Returns device used for reading zip archive.
+*/
+QIODevice* QZipReader::device() const
+{
+ return d->device;
+}
+
+/*!
Returns true if the user can read the file; otherwise returns false.
*/
bool QZipReader::isReadable() const
@@ -796,6 +826,7 @@ int QZipReader::count() const
/*!
Returns a FileInfo of an entry in the zipfile.
The \a index is the index into the directoy listing of the zipfile.
+ Returns an invalid FileInfo if \a index is out of boundaries.
\sa fileInfoList()
*/
@@ -803,7 +834,8 @@ QZipReader::FileInfo QZipReader::entryInfoAt(int index) const
{
d->scanFiles();
QZipReader::FileInfo fi;
- d->fillFileInfo(index, fi);
+ if (index >= 0 && index < d->fileHeaders.count())
+ d->fillFileInfo(index, fi);
return fi;
}
@@ -1022,6 +1054,14 @@ QZipWriter::~QZipWriter()
}
/*!
+ Returns device used for writing zip archive.
+*/
+QIODevice* QZipWriter::device() const
+{
+ return d->device;
+}
+
+/*!
Returns true if the user can write to the archive; otherwise returns false.
*/
bool QZipWriter::isWritable() const
diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h
index 67a2ace..6466a7b 100644
--- a/src/gui/text/qzipreader_p.h
+++ b/src/gui/text/qzipreader_p.h
@@ -55,6 +55,7 @@
// We mean it.
//
+#include <QtCore/qdatetime.h>
#include <QtCore/qfile.h>
#include <QtCore/qstring.h>
@@ -62,7 +63,7 @@ QT_BEGIN_NAMESPACE
class QZipReaderPrivate;
-class Q_AUTOTEST_EXPORT QZipReader
+class Q_GUI_EXPORT QZipReader
{
public:
QZipReader(const QString &fileName, QIODevice::OpenMode mode = QIODevice::ReadOnly );
@@ -70,15 +71,18 @@ public:
explicit QZipReader(QIODevice *device);
~QZipReader();
+ QIODevice* device() const;
+
bool isReadable() const;
bool exists() const;
- struct Q_AUTOTEST_EXPORT FileInfo
+ struct Q_GUI_EXPORT FileInfo
{
FileInfo();
FileInfo(const FileInfo &other);
~FileInfo();
FileInfo &operator=(const FileInfo &other);
+ bool isValid() const;
QString filePath;
uint isDir : 1;
uint isFile : 1;
@@ -86,6 +90,7 @@ public:
QFile::Permissions permissions;
uint crc32;
qint64 size;
+ QDateTime lastModified;
void *d;
};
diff --git a/src/gui/text/qzipwriter_p.h b/src/gui/text/qzipwriter_p.h
index 9322f4a..a50c172 100644
--- a/src/gui/text/qzipwriter_p.h
+++ b/src/gui/text/qzipwriter_p.h
@@ -69,6 +69,8 @@ public:
explicit QZipWriter(QIODevice *device);
~QZipWriter();
+ QIODevice* device() const;
+
bool isWritable() const;
bool exists() const;
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index b7615a4..9ec3142 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -37,7 +37,9 @@ HEADERS += \
text/qtexttable_p.h \
text/qzipreader_p.h \
text/qzipwriter_p.h \
- text/qtextodfwriter_p.h
+ text/qtextodfwriter_p.h \
+ text/qstatictext_p.h \
+ text/qstatictext.h
SOURCES += \
text/qfont.cpp \
@@ -66,7 +68,8 @@ SOURCES += \
text/qsyntaxhighlighter.cpp \
text/qcssparser.cpp \
text/qzip.cpp \
- text/qtextodfwriter.cpp
+ text/qtextodfwriter.cpp \
+ text/qstatictext.cpp
win32 {
SOURCES += \