summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2009-12-28 17:32:23 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2009-12-28 17:32:23 (GMT)
commit84f100353ba8352dc917baefeabb64ea7d5bcacd (patch)
tree3e54d2930012b07609ca453cd32d51bd53b3093e /src
parent48d2b516c6713160c29850a0a253ee295620d681 (diff)
parent8c306f8ee137baebc312a126c4e0d27bb9150f69 (diff)
downloadQt-84f100353ba8352dc917baefeabb64ea7d5bcacd.zip
Qt-84f100353ba8352dc917baefeabb64ea7d5bcacd.tar.gz
Qt-84f100353ba8352dc917baefeabb64ea7d5bcacd.tar.bz2
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.6-integration
* '4.6' of scm.dev.nokia.troll.no:qt/oslo-staging-2: QUrl::toEncoded() fix for the case of "password, but no username". Fix tst_QFileInfo::isHidden_data on Windows QStyleSheetStyle: Fixed some text croped when having padding with native border. Lots of mostly cosmetic cleanups to GL2 paint engine Move the 0.5 offset we add for aliased rendering to updateMatrix() revert f36fb8b2b63b3734cc2bd66b329ca4fef1204845 Read QWS_SIZE from layer rather than screen Get rid of no_cast_from_ascii warning Docs: Amendments to latest changes to QImageReader docs. images: Document QImageReader::loopCount behaviour for infinite loops gif: Add unit test for QImageReader::size calls gif: 10% speedup on microbenchmark on QImageReader png: Avoid calling QImage::scanLine(int) from within a loop QImageReader: Avoid errorString creation in the normal case Fix text rendering on GL2 paint engine
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp5
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp9
-rw-r--r--src/corelib/io/qurl.cpp14
-rw-r--r--src/gui/image/qimagereader.cpp42
-rw-r--r--src/gui/image/qpnghandler.cpp5
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp2
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp6
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h4
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp253
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h90
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp11
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.cpp40
12 files changed, 262 insertions, 219 deletions
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 71414ce..ea262bf 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -825,10 +825,9 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
ret |= RootFlag;
} else {
QString baseName = fileName(BaseName);
- if ((baseName.size() > 1
- && baseName.at(0) == QLatin1Char('.') && baseName.at(1) != QLatin1Char('.'))
+ if ((baseName.size() > 0 && baseName.at(0) == QLatin1Char('.'))
# if !defined(QWS) && defined(Q_OS_MAC)
- || _q_isMacHidden(d->filePath)
+ || _q_isMacHidden(d->filePath)
# endif
) {
ret |= HiddenFlag;
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index a6cb5a9..a7719a8 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -1595,13 +1595,10 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil
ret |= LocalDiskFlag;
if (d->doStat()) {
ret |= ExistsFlag;
- if (d->filePath == QLatin1String("/") || isDriveRoot(d->filePath) || isUncRoot(d->filePath)) {
+ if (d->filePath == QLatin1String("/") || isDriveRoot(d->filePath) || isUncRoot(d->filePath))
ret |= RootFlag;
- } else if (d->fileAttrib & FILE_ATTRIBUTE_HIDDEN) {
- QString baseName = fileName(BaseName);
- if (baseName != QLatin1String(".") && baseName != QLatin1String(".."))
- ret |= HiddenFlag;
- }
+ else if (d->fileAttrib & FILE_ATTRIBUTE_HIDDEN)
+ ret |= HiddenFlag;
}
}
return ret;
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index fd51bcf..6ac6468 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -3864,14 +3864,18 @@ QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const
url += "//";
if ((options & QUrl::RemoveUserInfo) != QUrl::RemoveUserInfo) {
+ bool hasUserOrPass = false;
if (!userName.isEmpty()) {
url += encodedUserName;
- if (!(options & QUrl::RemovePassword) && !password.isEmpty()) {
- url += ':';
- url += encodedPassword;
- }
- url += '@';
+ hasUserOrPass = true;
}
+ if (!(options & QUrl::RemovePassword) && !password.isEmpty()) {
+ url += ':';
+ url += encodedPassword;
+ hasUserOrPass = true;
+ }
+ if (hasUserOrPass)
+ url += '@';
}
if (host.startsWith(QLatin1Char('['))) {
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 074f3eb..7580446 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -471,7 +471,6 @@ QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq)
handler = 0;
quality = -1;
imageReaderError = QImageReader::UnknownError;
- errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unknown error"));
q = qq;
}
@@ -1214,11 +1213,12 @@ bool QImageReader::jumpToImage(int imageNumber)
}
/*!
- For image formats that support animation, this function returns
- the number of times the animation should loop. Otherwise, it
- returns -1.
+ For image formats that support animation, this function returns the number
+ of times the animation should loop. If this function returns -1, it can
+ either mean the animation should loop forever, or that an error occurred.
+ If an error occurred, canRead() will return false.
- \sa supportsAnimation(), QImageIOHandler::loopCount()
+ \sa supportsAnimation(), QImageIOHandler::loopCount(), canRead()
*/
int QImageReader::loopCount() const
{
@@ -1228,13 +1228,13 @@ int QImageReader::loopCount() const
}
/*!
- For image formats that support animation, this function returns
- the total number of images in the animation.
+ For image formats that support animation, this function returns the total
+ number of images in the animation. If the format does not support
+ animation, 0 is returned.
- Certain animation formats do not support this feature, in which
- case 0 is returned.
+ This function returns -1 if an error occurred.
- \sa supportsAnimation(), QImageIOHandler::imageCount()
+ \sa supportsAnimation(), QImageIOHandler::imageCount(), canRead()
*/
int QImageReader::imageCount() const
{
@@ -1244,11 +1244,13 @@ int QImageReader::imageCount() const
}
/*!
- For image formats that support animation, this function returns
- the number of milliseconds to wait until displaying the next frame
- in the animation. Otherwise, 0 is returned.
+ For image formats that support animation, this function returns the number
+ of milliseconds to wait until displaying the next frame in the animation.
+ If the image format doesn't support animation, 0 is returned.
+
+ This function returns -1 if an error occurred.
- \sa supportsAnimation(), QImageIOHandler::nextImageDelay()
+ \sa supportsAnimation(), QImageIOHandler::nextImageDelay(), canRead()
*/
int QImageReader::nextImageDelay() const
{
@@ -1258,11 +1260,13 @@ int QImageReader::nextImageDelay() const
}
/*!
- For image formats that support animation, this function returns
- the sequence number of the current frame. Otherwise, -1 is
- returned.
+ For image formats that support animation, this function returns the
+ sequence number of the current frame. If the image format doesn't support
+ animation, 0 is returned.
+
+ This function returns -1 if an error occurred.
- \sa supportsAnimation(), QImageIOHandler::currentImageNumber()
+ \sa supportsAnimation(), QImageIOHandler::currentImageNumber(), canRead()
*/
int QImageReader::currentImageNumber() const
{
@@ -1302,6 +1306,8 @@ QImageReader::ImageReaderError QImageReader::error() const
*/
QString QImageReader::errorString() const
{
+ if (d->errorString.isEmpty())
+ return QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unknown error"));
return d->errorString;
}
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 14c863b..1de0f32 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -67,6 +67,9 @@ QT_BEGIN_NAMESPACE
# define Q_INTERNAL_WIN_NO_THROW
#endif
+// avoid going through QImage::scanLine() which calls detach
+#define FAST_SCAN_LINE(data, bpl, y) (data + (y) * bpl)
+
/*
All PNG files load to the minimal QImage equivalent.
@@ -510,7 +513,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage)
&& outImage->format() == QImage::Format_Indexed8) {
int color_table_size = outImage->colorCount();
for (int y=0; y<(int)height; ++y) {
- uchar *p = outImage->scanLine(y);
+ uchar *p = FAST_SCAN_LINE(data, bpl, y);
uchar *end = p + width;
while (p < end) {
if (*p >= color_table_size)
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index 8b40931..aff3ac0 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -1065,7 +1065,7 @@ QRect QRenderRule::boxRect(const QRect& cr, int flags) const
r.adjust(-p[LeftEdge], -p[TopEdge], p[RightEdge], p[BottomEdge]);
}
}
- if (!hasNativeBorder() && (flags & Border)) {
+ if (hasBorder() && (flags & Border)) {
const int *b = border()->borders;
r.adjust(-b[LeftEdge], -b[TopEdge], b[RightEdge], b[BottomEdge]);
}
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index 9d545b9..1d3801c 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -393,7 +393,7 @@ QGLEngineShaderManager::~QGLEngineShaderManager()
removeCustomStage();
}
-uint QGLEngineShaderManager::getUniformLocation(Uniform id)
+GLuint QGLEngineShaderManager::getUniformLocation(const Uniform id)
{
if (!currentShaderProg)
return 0;
@@ -428,9 +428,9 @@ uint QGLEngineShaderManager::getUniformLocation(Uniform id)
}
-void QGLEngineShaderManager::optimiseForBrushTransform(const QTransform &transform)
+void QGLEngineShaderManager::optimiseForBrushTransform(const QTransform::TransformationType transformType)
{
- Q_UNUSED(transform); // Currently ignored
+ Q_UNUSED(transformType); // Currently ignored
}
void QGLEngineShaderManager::setDirty()
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
index 50c1432..3749b5c 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
@@ -454,7 +454,7 @@ public:
// There are optimisations we can do, depending on the brush transform:
// 1) May not have to apply perspective-correction
// 2) Can use lower precision for matrix
- void optimiseForBrushTransform(const QTransform &transform);
+ void optimiseForBrushTransform(const QTransform::TransformationType transformType);
void setSrcPixelType(Qt::BrushStyle);
void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images
void setOpacityMode(OpacityMode);
@@ -463,7 +463,7 @@ public:
void setCustomStage(QGLCustomShaderStage* stage);
void removeCustomStage();
- uint getUniformLocation(Uniform id);
+ GLuint getUniformLocation(const Uniform id);
void setDirty(); // someone has manually changed the current shader program
bool useCorrectShaderProg(); // returns true if the shader program needed to be changed
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index f52ed92..d3a9547 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -358,10 +358,10 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate()
void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id)
{
// glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit?
- if (id != GLuint(-1) && id == lastTexture)
+ if (id != GLuint(-1) && id == lastTextureUsed)
return;
- lastTexture = id;
+ lastTextureUsed = id;
if (smoothPixmapTransform) {
glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -388,23 +388,26 @@ inline QColor qt_premultiplyColor(QColor c, GLfloat opacity)
void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush)
{
- Q_ASSERT(brush.style() != Qt::NoBrush);
-
if (qbrush_fast_equals(currentBrush, brush))
return;
+ const Qt::BrushStyle newStyle = qbrush_style(brush);
+ Q_ASSERT(newStyle != Qt::NoBrush);
+
currentBrush = brush;
+ brushUniformsDirty = true; // All brushes have at least one uniform
+
+ if (newStyle > Qt::SolidPattern)
+ brushTextureDirty = true;
- brushTextureDirty = true;
- brushUniformsDirty = true;
if (currentBrush.style() == Qt::TexturePattern
&& qHasPixmapTexture(brush) && brush.texture().isQBitmap())
{
shaderManager->setSrcPixelType(QGLEngineShaderManager::TextureSrcWithPattern);
} else {
- shaderManager->setSrcPixelType(currentBrush.style());
+ shaderManager->setSrcPixelType(newStyle);
}
- shaderManager->optimiseForBrushTransform(currentBrush.transform());
+ shaderManager->optimiseForBrushTransform(currentBrush.transform().type());
}
@@ -605,12 +608,18 @@ void QGL2PaintEngineExPrivate::updateMatrix()
const GLfloat wfactor = 2.0f / width;
const GLfloat hfactor = -2.0f / height;
+ if (addOffset) {
+ pmvMatrix[2][0] = (wfactor * (transform.dx() + 0.49f)) - transform.m33();
+ pmvMatrix[2][1] = (hfactor * (transform.dy() + 0.49f)) + transform.m33();
+ } else {
+ pmvMatrix[2][0] = (wfactor * transform.dx()) - transform.m33();
+ pmvMatrix[2][1] = (hfactor * transform.dy()) + transform.m33();
+ }
+
pmvMatrix[0][0] = (wfactor * transform.m11()) - transform.m13();
pmvMatrix[1][0] = (wfactor * transform.m21()) - transform.m23();
- pmvMatrix[2][0] = (wfactor * transform.dx() ) - transform.m33();
pmvMatrix[0][1] = (hfactor * transform.m12()) + transform.m13();
pmvMatrix[1][1] = (hfactor * transform.m22()) + transform.m23();
- pmvMatrix[2][1] = (hfactor * transform.dy() ) + transform.m33();
pmvMatrix[0][2] = transform.m13();
pmvMatrix[1][2] = transform.m23();
pmvMatrix[2][2] = transform.m33();
@@ -700,7 +709,14 @@ static inline void setCoords(GLfloat *coords, const QGLRect &rect)
void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern)
{
// Setup for texture drawing
+ currentBrush = noBrush;
shaderManager->setSrcPixelType(pattern ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
+
+ if (addOffset) {
+ addOffset = false;
+ matrixDirty = true;
+ }
+
if (prepareForDraw(opaque))
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
@@ -755,7 +771,7 @@ void QGL2PaintEngineEx::beginNativePainting()
Q_UNUSED(ctx);
#endif
- d->lastTexture = GLuint(-1);
+ d->lastTextureUsed = GLuint(-1);
d->dirtyStencilRegion = QRect(0, 0, d->width, d->height);
d->resetGLState();
@@ -782,12 +798,6 @@ void QGL2PaintEngineEx::endNativePainting()
d->needsSync = true;
}
-const QGLContext *QGL2PaintEngineEx::context()
-{
- Q_D(QGL2PaintEngineEx);
- return d->ctx;
-}
-
void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
{
if (newMode == mode)
@@ -798,7 +808,7 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
glDisableVertexAttribArray(QT_OPACITY_ATTR);
- lastTexture = GLuint(-1);
+ lastTextureUsed = GLuint(-1);
}
if (newMode == TextDrawingMode) {
@@ -846,13 +856,14 @@ struct QGL2PEVectorPathCache
qreal iscale;
};
-void qopengl2paintengine_cleanup_vectorpath(QPaintEngineEx *engine, void *data)
+void QGL2PaintEngineExPrivate::cleanupVectorPath(QPaintEngineEx *engine, void *data)
{
QGL2PEVectorPathCache *c = (QGL2PEVectorPathCache *) data;
#ifdef QT_OPENGL_CACHE_AS_VBOS
- QGL2PaintEngineExPrivate *d = QGL2PaintEngineExPrivate::getData((QGL2PaintEngineEx *) engine);
- d->unusedVBOSToClean << c->vbo;
+ Q_ASSERT(engine->type() == QPaintEngine::OpenGL2);
+ static_cast<QGL2PaintEngineEx *>(engine)->d_func()->unusedVBOSToClean << c->vbo;
#else
+ Q_UNUSED(engine);
qFree(c->vertices);
#endif
delete c;
@@ -863,6 +874,16 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
{
transferMode(BrushDrawingMode);
+ const QOpenGL2PaintEngineState *s = q->state();
+ const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) &&
+ (qbrush_style(currentBrush) == Qt::SolidPattern) &&
+ !multisamplingAlwaysEnabled;
+
+ if (addOffset != newAddOffset) {
+ addOffset = newAddOffset;
+ matrixDirty = true;
+ }
+
// Might need to call updateMatrix to re-calculate inverseScale
if (matrixDirty)
updateMatrix();
@@ -898,7 +919,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
} else {
cache = new QGL2PEVectorPathCache;
cache->vertexCount = 0;
- data = const_cast<QVectorPath &>(path).addCacheData(q, cache, qopengl2paintengine_cleanup_vectorpath);
+ data = const_cast<QVectorPath &>(path).addCacheData(q, cache, cleanupVectorPath);
}
// Flatten the path at the current scale factor and fill it into the cache struct.
@@ -1274,31 +1295,14 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush)
{
Q_D(QGL2PaintEngineEx);
- Qt::BrushStyle style = qbrush_style(brush);
- if (style == Qt::NoBrush)
+ if (qbrush_style(brush) == Qt::NoBrush)
return;
+
if (!d->inRenderText)
ensureActive();
- QOpenGL2PaintEngineState *s = state();
- bool doOffset = !(s->renderHints & QPainter::Antialiasing) &&
- (style == Qt::SolidPattern) &&
- !d->multisamplingAlwaysEnabled;
-
- if (doOffset) {
- d->temporaryTransform = s->matrix;
- QTransform tx = QTransform::fromTranslate(.49, .49);
- s->matrix = s->matrix * tx;
- d->matrixDirty = true;
- }
-
d->setBrush(brush);
d->fill(path);
-
- if (doOffset) {
- s->matrix = d->temporaryTransform;
- d->matrixDirty = true;
- }
}
extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
@@ -1308,9 +1312,8 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
{
Q_D(QGL2PaintEngineEx);
- Qt::PenStyle penStyle = qpen_style(pen);
const QBrush &penBrush = qpen_brush(pen);
- if (penStyle == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush)
+ if (qpen_style(pen) == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush)
return;
QOpenGL2PaintEngineState *s = state();
@@ -1321,45 +1324,47 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
}
ensureActive();
+ d->setBrush(penBrush);
+ d->stroke(path, pen);
+}
- bool doOffset = !(s->renderHints & QPainter::Antialiasing) && !d->multisamplingAlwaysEnabled;
- if (doOffset) {
- d->temporaryTransform = s->matrix;
- QTransform tx = QTransform::fromTranslate(0.49, .49);
- s->matrix = s->matrix * tx;
- d->matrixDirty = true;
+void QGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &pen)
+{
+ const QOpenGL2PaintEngineState *s = q->state();
+ const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) && !multisamplingAlwaysEnabled;
+ if (addOffset != newAddOffset) {
+ addOffset = newAddOffset;
+ matrixDirty = true;
}
- bool opaque = penBrush.isOpaque() && s->opacity > 0.99;
- d->setBrush(penBrush);
- d->transferMode(BrushDrawingMode);
+ const Qt::PenStyle penStyle = qpen_style(pen);
+ const QBrush &penBrush = qpen_brush(pen);
+ const bool opaque = penBrush.isOpaque() && s->opacity > 0.99;
+
+ transferMode(BrushDrawingMode);
// updateMatrix() is responsible for setting the inverse scale on
// the strokers, so we need to call it here and not wait for
// prepareForDraw() down below.
- d->updateMatrix();
+ updateMatrix();
if (penStyle == Qt::SolidLine) {
- d->stroker.process(path, pen);
+ stroker.process(path, pen);
} else { // Some sort of dash
- d->dasher.process(path, pen);
+ dasher.process(path, pen);
- QVectorPath dashStroke(d->dasher.points(),
- d->dasher.elementCount(),
- d->dasher.elementTypes());
- d->stroker.process(dashStroke, pen);
+ QVectorPath dashStroke(dasher.points(),
+ dasher.elementCount(),
+ dasher.elementTypes());
+ stroker.process(dashStroke, pen);
}
-
- QGLContext *ctx = d->ctx;
- Q_UNUSED(ctx);
-
if (opaque) {
- d->prepareForDraw(opaque);
+ prepareForDraw(opaque);
glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
- glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, d->stroker.vertices());
- glDrawArrays(GL_TRIANGLE_STRIP, 0, d->stroker.vertexCount() / 2);
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, stroker.vertices());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, stroker.vertexCount() / 2);
// QBrush b(Qt::green);
// d->setBrush(&b);
@@ -1377,30 +1382,25 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
: width;
if (pen.isCosmetic())
- extra = extra * d->inverseScale;
+ extra = extra * inverseScale;
QRectF bounds = path.controlPointRect().adjusted(-extra, -extra, extra, extra);
- d->fillStencilWithVertexArray(d->stroker.vertices(), d->stroker.vertexCount() / 2,
+ fillStencilWithVertexArray(stroker.vertices(), stroker.vertexCount() / 2,
0, 0, bounds, QGL2PaintEngineExPrivate::TriStripStrokeFillMode);
glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
// Pass when any bit is set, replace stencil value with 0
glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
- d->prepareForDraw(false);
+ prepareForDraw(false);
// Stencil the brush onto the dest buffer
- d->composite(bounds);
+ composite(bounds);
glStencilMask(0);
- d->updateClipScissorTest();
- }
-
- if (doOffset) {
- s->matrix = d->temporaryTransform;
- d->matrixDirty = true;
+ updateClipScissorTest();
}
}
@@ -1440,7 +1440,7 @@ void QGL2PaintEngineEx::renderHintsChanged()
#endif
Q_D(QGL2PaintEngineEx);
- d->lastTexture = GLuint(-1);
+ d->lastTextureUsed = GLuint(-1);
d->brushTextureDirty = true;
// qDebug("QGL2PaintEngineEx::renderHintsChanged() not implemented!");
}
@@ -1609,6 +1609,11 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly
if (textureCoordinateArray.data() != oldTextureCoordinateDataPtr)
glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
+ if (addOffset) {
+ addOffset = false;
+ matrixDirty = true;
+ }
+
QBrush pensBrush = q->state()->pen.brush();
setBrush(pensBrush);
@@ -1706,20 +1711,31 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly
void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
{
+ Q_D(QGL2PaintEngineEx);
// Use fallback for extended composition modes.
if (state()->composition_mode > QPainter::CompositionMode_Plus) {
QPaintEngineEx::drawPixmaps(drawingData, dataCount, pixmap, hints);
return;
}
- Q_D(QGL2PaintEngineEx);
+ ensureActive();
+ d->drawPixmaps(drawingData, dataCount, pixmap, hints);
+}
+
+void QGL2PaintEngineExPrivate::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
+{
GLfloat dx = 1.0f / pixmap.size().width();
GLfloat dy = 1.0f / pixmap.size().height();
- d->vertexCoordinateArray.clear();
- d->textureCoordinateArray.clear();
- d->opacityArray.reset();
+ vertexCoordinateArray.clear();
+ textureCoordinateArray.clear();
+ opacityArray.reset();
+
+ if (addOffset) {
+ addOffset = false;
+ matrixDirty = true;
+ }
bool allOpaque = true;
@@ -1736,31 +1752,28 @@ void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int d
QGLPoint bottomRight(right * c - bottom * s, right * s + bottom * c);
QGLPoint bottomLeft(-right * c - bottom * s, -right * s + bottom * c);
- d->vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y());
- d->vertexCoordinateArray.lineToArray(-bottomLeft.x + drawingData[i].point.x(), -bottomLeft.y + drawingData[i].point.y());
- d->vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y());
- d->vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y());
- d->vertexCoordinateArray.lineToArray(bottomLeft.x + drawingData[i].point.x(), bottomLeft.y + drawingData[i].point.y());
- d->vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y());
+ vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y());
+ vertexCoordinateArray.lineToArray(-bottomLeft.x + drawingData[i].point.x(), -bottomLeft.y + drawingData[i].point.y());
+ vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y());
+ vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y());
+ vertexCoordinateArray.lineToArray(bottomLeft.x + drawingData[i].point.x(), bottomLeft.y + drawingData[i].point.y());
+ vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y());
QGLRect src(drawingData[i].source.left() * dx, drawingData[i].source.top() * dy,
drawingData[i].source.right() * dx, drawingData[i].source.bottom() * dy);
- d->textureCoordinateArray.lineToArray(src.right, src.bottom);
- d->textureCoordinateArray.lineToArray(src.right, src.top);
- d->textureCoordinateArray.lineToArray(src.left, src.top);
- d->textureCoordinateArray.lineToArray(src.left, src.top);
- d->textureCoordinateArray.lineToArray(src.left, src.bottom);
- d->textureCoordinateArray.lineToArray(src.right, src.bottom);
+ textureCoordinateArray.lineToArray(src.right, src.bottom);
+ textureCoordinateArray.lineToArray(src.right, src.top);
+ textureCoordinateArray.lineToArray(src.left, src.top);
+ textureCoordinateArray.lineToArray(src.left, src.top);
+ textureCoordinateArray.lineToArray(src.left, src.bottom);
+ textureCoordinateArray.lineToArray(src.right, src.bottom);
- qreal opacity = drawingData[i].opacity * state()->opacity;
- d->opacityArray << opacity << opacity << opacity << opacity << opacity << opacity;
+ qreal opacity = drawingData[i].opacity * q->state()->opacity;
+ opacityArray << opacity << opacity << opacity << opacity << opacity << opacity;
allOpaque &= (opacity >= 0.99f);
}
- ensureActive();
-
- QGLContext *ctx = d->ctx;
glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA,
QGLContext::InternalBindOption
@@ -1768,27 +1781,28 @@ void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int d
if (texture->options & QGLContext::InvertedYBindOption) {
// Flip texture y-coordinate.
- QGLPoint *data = d->textureCoordinateArray.data();
+ QGLPoint *data = textureCoordinateArray.data();
for (int i = 0; i < 6 * dataCount; ++i)
data[i].y = 1 - data[i].y;
}
- d->transferMode(ImageArrayDrawingMode);
+ transferMode(ImageArrayDrawingMode);
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && (!pixmap.hasAlphaChannel() || (hints & QDrawPixmaps::OpaqueHint)) && allOpaque;
- d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
- state()->renderHints & QPainter::SmoothPixmapTransform, texture->id);
+ updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
+ q->state()->renderHints & QPainter::SmoothPixmapTransform, texture->id);
// Setup for texture drawing
- d->shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
- if (d->prepareForDraw(isOpaque))
- d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
+ currentBrush = noBrush;
+ shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
+ if (prepareForDraw(isOpaque))
+ shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
if (isBitmap) {
- QColor col = qt_premultiplyColor(state()->pen.color(), (GLfloat)state()->opacity);
- d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::PatternColor), col);
+ QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity);
+ shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
}
glDrawArrays(GL_TRIANGLES, 0, 6 * dataCount);
@@ -1820,7 +1834,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->compositionModeDirty = true;
d->opacityUniformDirty = true;
d->needsSync = true;
- d->use_system_clip = !systemClip().isEmpty();
+ d->useSystemClip = !systemClip().isEmpty();
d->currentBrush = QBrush();
d->dirtyStencilRegion = QRect(0, 0, d->width, d->height);
@@ -1941,12 +1955,12 @@ void QGL2PaintEngineExPrivate::updateClipScissorTest()
#else
QRect bounds = q->state()->rectangleClip;
if (!q->state()->clipEnabled) {
- if (use_system_clip)
+ if (useSystemClip)
bounds = systemClip.boundingRect();
else
bounds = QRect(0, 0, width, height);
} else {
- if (use_system_clip)
+ if (useSystemClip)
bounds = bounds.intersected(systemClip.boundingRect());
else
bounds = bounds.intersected(QRect(0, 0, width, height));
@@ -2001,6 +2015,11 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value)
{
transferMode(BrushDrawingMode);
+ if (addOffset) {
+ addOffset = false;
+ matrixDirty = true;
+ }
+
if (matrixDirty)
updateMatrix();
@@ -2100,7 +2119,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op)
switch (op) {
case Qt::NoClip:
- if (d->use_system_clip) {
+ if (d->useSystemClip) {
state()->clipTestEnabled = true;
state()->currentClip = 1;
} else {
@@ -2172,13 +2191,13 @@ void QGL2PaintEngineExPrivate::systemStateChanged()
q->state()->clipChanged = true;
if (systemClip.isEmpty()) {
- use_system_clip = false;
+ useSystemClip = false;
} else {
if (q->paintDevice()->devType() == QInternal::Widget && currentClipWidget) {
QWidgetPrivate *widgetPrivate = qt_widget_private(currentClipWidget->window());
- use_system_clip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter;
+ useSystemClip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter;
} else {
- use_system_clip = true;
+ useSystemClip = true;
}
}
@@ -2188,19 +2207,19 @@ void QGL2PaintEngineExPrivate::systemStateChanged()
q->state()->currentClip = 1;
maxClip = 1;
- q->state()->rectangleClip = use_system_clip ? systemClip.boundingRect() : QRect(0, 0, width, height);
+ q->state()->rectangleClip = useSystemClip ? systemClip.boundingRect() : QRect(0, 0, width, height);
updateClipScissorTest();
if (systemClip.rectCount() == 1) {
if (systemClip.boundingRect() == QRect(0, 0, width, height))
- use_system_clip = false;
+ useSystemClip = false;
#ifndef QT_GL_NO_SCISSOR_TEST
// scissoring takes care of the system clip
return;
#endif
}
- if (use_system_clip) {
+ if (useSystemClip) {
clearClip(0);
QPainterPath path;
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index f1ec6e6..c94c4f4 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -105,13 +105,8 @@ public:
~QGL2PaintEngineEx();
bool begin(QPaintDevice *device);
- bool end();
-
void ensureActive();
-
- virtual void fill(const QVectorPath &path, const QBrush &brush);
- virtual void stroke(const QVectorPath &path, const QPen &pen);
- virtual void clip(const QVectorPath &path, Qt::ClipOperation op);
+ bool end();
virtual void clipEnabledChanged();
virtual void penChanged();
@@ -122,20 +117,21 @@ public:
virtual void renderHintsChanged();
virtual void transformChanged();
-
+ virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr);
virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
+ virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints);
virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
Qt::ImageConversionFlags flags = Qt::AutoColor);
- virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr);
-
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
+ virtual void fill(const QVectorPath &path, const QBrush &brush);
+ virtual void stroke(const QVectorPath &path, const QPen &pen);
+ virtual void clip(const QVectorPath &path, Qt::ClipOperation op);
- virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints);
Type type() const { return OpenGL2; }
- void setState(QPainterState *s);
- QPainterState *createState(QPainterState *orig) const;
+ virtual void setState(QPainterState *s);
+ virtual QPainterState *createState(QPainterState *orig) const;
inline QOpenGL2PaintEngineState *state() {
return static_cast<QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
}
@@ -146,8 +142,6 @@ public:
void beginNativePainting();
void endNativePainting();
- const QGLContext* context();
-
QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype);
void setRenderTextActive(bool);
@@ -169,10 +163,12 @@ public:
QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) :
q(q_ptr),
+ shaderManager(0),
width(0), height(0),
ctx(0),
+ useSystemClip(true),
+ addOffset(false),
inverseScale(1),
- shaderManager(0),
inRenderText(false)
{ }
@@ -184,45 +180,62 @@ public:
void updateCompositionMode();
void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = -1);
- void setBrush(const QBrush& brush);
-
- void transferMode(EngineMode newMode);
void resetGLState();
- // fill, drawOutline, drawTexture & drawCachedGlyphs are the rendering entry points:
+ // fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points,
+ // however writeClip can also be thought of as en entry point as it does similar things.
void fill(const QVectorPath &path);
+ void stroke(const QVectorPath &path, const QPen &pen);
void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false);
+ void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints);
void drawCachedGlyphs(const QPointF &p, QFontEngineGlyphCache::Type glyphType, const QTextItemInt &ti);
+ // draws whatever is in the vertex array:
void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive);
void drawVertexArrays(QGL2PEXVertexArray &vertexArray, GLenum primitive) {
drawVertexArrays((const float *) vertexArray.data(), vertexArray.stops(), vertexArray.stopCount(), primitive);
}
- // ^ draws whatever is in the vertex array
+ // Composites the bounding rect onto dest buffer:
void composite(const QGLRect& boundingRect);
- // ^ Composites the bounding rect onto dest buffer
+ // Calls drawVertexArrays to render into stencil buffer:
void fillStencilWithVertexArray(const float *data, int count, int *stops, int stopCount, const QGLRect &bounds, StencilFillMode mode);
void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill) {
fillStencilWithVertexArray((const float *) vertexArray.data(), 0, vertexArray.stops(), vertexArray.stopCount(),
vertexArray.boundingRect(),
useWindingFill ? WindingFillMode : OddEvenFillMode);
}
- // ^ Calls drawVertexArrays to render into stencil buffer
-
- bool prepareForDraw(bool srcPixelsAreOpaque);
- // ^ returns whether the current program changed or not
+ void setBrush(const QBrush& brush);
+ void transferMode(EngineMode newMode);
+ bool prepareForDraw(bool srcPixelsAreOpaque); // returns true if the program has changed
inline void useSimpleShader();
+ inline GLuint location(const QGLEngineShaderManager::Uniform uniform) {
+ return shaderManager->getUniformLocation(uniform);
+ }
+
void prepareDepthRangeForRenderText();
void restoreDepthRangeForRenderText();
+ void clearClip(uint value);
+ void writeClip(const QVectorPath &path, uint value);
+ void resetClipIfNeeded();
+
+ void updateClipScissorTest();
+ void setScissor(const QRect &rect);
+ void regenerateClip();
+ void systemStateChanged();
+
+
static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; }
static QGL2PaintEngineExPrivate *getData(QGL2PaintEngineEx *engine) { return engine->d_func(); }
+ static void cleanupVectorPath(QPaintEngineEx *engine, void *data);
+
QGL2PaintEngineEx* q;
+ QGLEngineShaderManager* shaderManager;
QGLPaintDevice* device;
int width, height;
QGLContext *ctx;
@@ -239,41 +252,25 @@ public:
bool opacityUniformDirty;
bool stencilClean; // Has the stencil not been used for clipping so far?
+ bool useSystemClip;
QRegion dirtyStencilRegion;
QRect currentScissorBounds;
uint maxClip;
QBrush currentBrush; // May not be the state's brush!
-
- GLfloat inverseScale;
+ const QBrush noBrush;
QGL2PEXVertexArray vertexCoordinateArray;
QGL2PEXVertexArray textureCoordinateArray;
QDataBuffer<GLfloat> opacityArray;
-
GLfloat staticVertexCoordinateArray[8];
GLfloat staticTextureCoordinateArray[8];
+ bool addOffset; // When enabled, adds a 0.49,0.49 offset to matrix in updateMatrix
GLfloat pmvMatrix[3][3];
+ GLfloat inverseScale;
- QGLEngineShaderManager* shaderManager;
-
- void clearClip(uint value);
- void writeClip(const QVectorPath &path, uint value);
- void resetClipIfNeeded();
-
- void updateClipScissorTest();
- void setScissor(const QRect &rect);
- void regenerateClip();
- void systemStateChanged();
- uint use_system_clip : 1;
-
- uint location(QGLEngineShaderManager::Uniform uniform)
- {
- return shaderManager->getUniformLocation(uniform);
- }
-
- GLuint lastTexture;
+ GLuint lastTextureUsed;
bool needsSync;
bool inRenderText;
@@ -285,7 +282,6 @@ public:
QTriangulatingStroker stroker;
QDashedStrokeProcessor dasher;
- QTransform temporaryTransform;
QScopedPointer<QPixmapFilter> convolutionFilter;
QScopedPointer<QPixmapFilter> colorizeFilter;
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
index 4744eb6..bb26d29 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
@@ -1063,7 +1063,7 @@ static inline bool setIntOption(const QStringList &arguments, const QString &var
static inline QColor colorFromName(const QString &name)
{
- QRegExp rx("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])");
+ QRegExp rx(QLatin1String("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])"));
rx.setCaseSensitivity(Qt::CaseInsensitive);
if (rx.exactMatch(name)) {
Q_ASSERT(rx.captureCount() == 4);
@@ -1278,7 +1278,14 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
#ifdef QT_NO_DIRECTFB_WM
result = d_ptr->primarySurface->GetSize(d_ptr->primarySurface, &w, &h);
#elif (Q_DIRECTFB_VERSION >= 0x010000)
- result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h);
+ IDirectFBSurface *layerSurface;
+ if (d_ptr->dfbLayer->GetSurface(d_ptr->dfbLayer, &layerSurface) != DFB_OK) {
+ result = layerSurface->GetSize(layerSurface, &w, &h);
+ layerSurface->Release(layerSurface);
+ }
+ if (w <= 0 || h <= 0) {
+ result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h);
+ }
#else
qWarning("QDirectFBScreen::connect: DirectFB versions prior to 1.0 do not offer a way\n"
"query the size of the primary surface in windowed mode. You have to specify\n"
diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp
index c95b63c..dee0e52 100644
--- a/src/plugins/imageformats/gif/qgifhandler.cpp
+++ b/src/plugins/imageformats/gif/qgifhandler.cpp
@@ -54,6 +54,10 @@ QT_BEGIN_NAMESPACE
#define Q_TRANSPARENT 0x00ffffff
+// avoid going through QImage::scanLine() which calls detach
+#define FAST_SCAN_LINE(bits, bpl, y) (bits + (y) * bpl)
+
+
/*
Incremental image decoder for GIF image format.
@@ -135,7 +139,7 @@ private:
int frame;
bool out_of_bounds;
bool digress;
- void nextY(QImage *image);
+ void nextY(unsigned char *bits, int bpl);
void disposePrevious(QImage *image);
};
@@ -232,6 +236,10 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
// CompuServe Incorporated. GIF(sm) is a Service Mark property of
// CompuServe Incorporated."
+ image->detach();
+ int bpl = image->bytesPerLine();
+ unsigned char *bits = image->bits();
+
#define LM(l, m) (((m)<<8)|l)
digress = false;
const int initial = length;
@@ -335,7 +343,9 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
QImage::Format format = trans_index >= 0 ? QImage::Format_ARGB32 : QImage::Format_RGB32;
if (image->isNull()) {
(*image) = QImage(swidth, sheight, format);
- memset(image->bits(), 0, image->byteCount());
+ bpl = image->bytesPerLine();
+ bits = image->bits();
+ memset(bits, 0, image->byteCount());
// ### size of the upcoming frame, should rather
// be known before decoding it.
@@ -393,11 +403,13 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
backingstore = QImage(qMax(backingstore.width(), w),
qMax(backingstore.height(), h),
QImage::Format_RGB32);
- memset(image->bits(), 0, image->byteCount());
+ memset(bits, 0, image->byteCount());
}
+ const int dest_bpl = backingstore.bytesPerLine();
+ unsigned char *dest_data = backingstore.bits();
for (int ln=0; ln<h; ln++) {
- memcpy(backingstore.scanLine(ln),
- image->scanLine(t+ln)+l, w*sizeof(QRgb));
+ memcpy(FAST_SCAN_LINE(dest_data, dest_bpl, ln),
+ FAST_SCAN_LINE(bits, bpl, t+ln) + l, w*sizeof(QRgb));
}
}
@@ -470,14 +482,14 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
if (needfirst) {
firstcode=oldcode=code;
if (!out_of_bounds && image->height() > y && firstcode!=trans_index)
- ((QRgb*)image->scanLine(y))[x] = color(firstcode);
+ ((QRgb*)FAST_SCAN_LINE(bits, bpl, y))[x] = color(firstcode);
x++;
if (x>=swidth) out_of_bounds = true;
needfirst=false;
if (x>=left+width) {
x=left;
out_of_bounds = left>=swidth || y>=sheight;
- nextY(image);
+ nextY(bits, bpl);
}
} else {
incode=code;
@@ -515,7 +527,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
const QRgb *map = lcmap ? localcmap : globalcmap;
QRgb *line = 0;
if (!out_of_bounds && h > y)
- line = (QRgb*)image->scanLine(y);
+ line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y);
while (sp>stack) {
const uchar index = *(--sp);
if (!out_of_bounds && h > y && index!=trans_index) {
@@ -529,9 +541,9 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
if (x>=left+width) {
x=left;
out_of_bounds = left>=swidth || y>=sheight;
- nextY(image);
+ nextY(bits, bpl);
if (!out_of_bounds && h > y)
- line = (QRgb*)image->scanLine(y);
+ line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y);
}
}
}
@@ -644,7 +656,7 @@ void QGIFFormat::fillRect(QImage *image, int col, int row, int w, int h, QRgb co
}
}
-void QGIFFormat::nextY(QImage *image)
+void QGIFFormat::nextY(unsigned char *bits, int bpl)
{
int my;
switch (interlace) {
@@ -660,7 +672,7 @@ void QGIFFormat::nextY(QImage *image)
// Don't dup with transparency
if (trans_index < 0) {
for (i=1; i<=my; i++) {
- memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb),
+ memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb),
(right-left+1)*sizeof(QRgb));
}
}
@@ -689,7 +701,7 @@ void QGIFFormat::nextY(QImage *image)
// Don't dup with transparency
if (trans_index < 0) {
for (i=1; i<=my; i++) {
- memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb),
+ memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb),
(right-left+1)*sizeof(QRgb));
}
}
@@ -713,7 +725,7 @@ void QGIFFormat::nextY(QImage *image)
// Don't dup with transparency
if (trans_index < 0) {
for (i=1; i<=my; i++) {
- memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb),
+ memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb),
(right-left+1)*sizeof(QRgb));
}
}