[Marble-commits] KDE/kdeedu/marble/src/lib

Bernhard Beschow bbeschow at cs.tu-berlin.de
Fri Jul 9 14:45:01 CEST 2010


SVN commit 1147952 by beschow:

don't load invalid images into texture tiles

* please review for possible memory leaks or invalid pointer accesses

 M  +4 -19     TextureTile.cpp  
 M  +10 -11    TextureTile.h  
 M  +26 -30    TileLoader.cpp  


--- trunk/KDE/kdeedu/marble/src/lib/TextureTile.cpp #1147951:1147952
@@ -22,22 +22,15 @@
 namespace Marble
 {
 
-TextureTile::TextureTile( TileId const & tileId )
+TextureTile::TextureTile( TileId const & tileId, QImage const * image )
     : m_id( tileId ),
-      m_state( StateEmpty ),
-      m_blending( 0 ),
-      m_expireSecs( std::numeric_limits<int>::max() ),
-      m_image( 0 )
-{
-}
-
-TextureTile::TextureTile( TileId const & tileId, QString const & fileName )
-    : m_id( tileId ),
       m_state( StateExpired ),
       m_blending( 0 ),
       m_expireSecs( std::numeric_limits<int>::max() ),
-      m_image( new QImage( fileName ))
+      m_image( image )
 {
+    Q_ASSERT( image );
+    Q_ASSERT( !image->isNull() );
 }
 
 TextureTile::~TextureTile()
@@ -45,12 +38,4 @@
     delete m_image;
 }
 
-void TextureTile::setImage( QByteArray const & data )
-{
-    if ( !m_image )
-        m_image = new QImage( QImage::fromData( data ));
-    else
-        m_image->loadFromData( data );
 }
-
-}
--- trunk/KDE/kdeedu/marble/src/lib/TextureTile.h #1147951:1147952
@@ -43,8 +43,7 @@
         StateUptodate
     };
 
-    explicit TextureTile( TileId const & );
-    TextureTile( TileId const & tileId, QString const & fileName );
+    TextureTile( TileId const & tileId, QImage const * image );
     ~TextureTile();
 
     TileId const & id() const;
@@ -52,7 +51,6 @@
     QDateTime const & lastModified() const;
     bool isExpired() const;
     QImage const * image() const;
-    QImage * image();
     State state() const;
     Blending const * blending() const;
     int byteCount() const;
@@ -61,7 +59,6 @@
     Q_DISABLE_COPY( TextureTile )
 
     void setState( State const );
-    void setImage( QByteArray const & data );
     void setImage( QImage * const );
     void setBlending( Blending const * const );
     void setStackedTileId( TileId const & );
@@ -74,7 +71,7 @@
     Blending const * m_blending;
     QDateTime m_lastModified;
     int m_expireSecs;
-    QImage * m_image;
+    QImage const * m_image;
 };
 
 
@@ -105,11 +102,6 @@
     return m_image;
 }
 
-inline QImage * TextureTile::image()
-{
-    return m_image;
-}
-
 inline TextureTile::State TextureTile::state() const
 {
     return m_state;
@@ -122,8 +114,10 @@
 
 inline int TextureTile::byteCount() const
 {
+    Q_ASSERT( m_image );
+
     // FIXME: once Qt 4.6 is required for Marble, use QImage::byteCount()
-    return m_image ? m_image->numBytes() : 0;
+    return m_image->numBytes();
 }
 
 inline void TextureTile::setState( State const state )
@@ -133,6 +127,11 @@
 
 inline void TextureTile::setImage( QImage * const image )
 {
+    Q_ASSERT( image );
+    Q_ASSERT( !image->isNull() );
+
+    delete m_image;
+
     m_image = image;
 }
 
--- trunk/KDE/kdeedu/marble/src/lib/TileLoader.cpp #1147951:1147952
@@ -48,14 +48,14 @@
                                                   DownloadUsage const usage )
 {
     QString const fileName = tileFileName( tileId );
-    QFileInfo const fileInfo( fileName );
-    if ( fileInfo.exists() ) {
+    QImage const image( fileName );
+    if ( !image.isNull() ) {
         // file is there, so create and return a tile object in any case,
         // but check if an update should be triggered
         GeoSceneTexture const * const textureLayer = findTextureLayer( tileId );
-        QSharedPointer<TextureTile> const tile( new TextureTile( tileId, fileName ));
+        QSharedPointer<TextureTile> const tile( new TextureTile( tileId, new QImage( image ) ));
         tile->setStackedTileId( stackedTileId );
-        tile->setLastModified( fileInfo.lastModified() );
+        tile->setLastModified( QFileInfo( fileName ).lastModified() );
         tile->setExpireSecs( textureLayer->expire() );
 
         if ( !tile->isExpired() ) {
@@ -71,18 +71,14 @@
 
     // tile was not locally available => trigger download and look for tiles in other levels
     // for scaling
-    QSharedPointer<TextureTile> const tile( new TextureTile( tileId ));
+    QImage * replacementTile = scaledLowerLevelTile( tileId );
+    QSharedPointer<TextureTile> const tile( new TextureTile( tileId, replacementTile ));
     tile->setStackedTileId( stackedTileId );
+    tile->setState( TextureTile::StateScaled );
+
     m_waitingForUpdate.insert( tileId, tile );
     triggerDownload( tileId, usage );
-    QImage * const replacementTile = scaledLowerLevelTile( tileId );
-    if ( replacementTile ) {
-        mDebug() << "TileLoader::loadTile" << tileId.toString() << "StateScaled";
-        tile->setImage( replacementTile );
-        tile->setState( TextureTile::StateScaled );
-    } else {
-        mDebug() << "TileLoader::loadTile" << tileId.toString() << "No tiles found";
-    }
+
     return tile;
 }
 
@@ -108,19 +104,16 @@
         return tile;
 
     QString const fileName = tileFileName( tileId );
-    QFileInfo const fileInfo( fileName );
-    if ( fileInfo.exists() ) {
-        tile = QSharedPointer<TextureTile>( new TextureTile( tileId, fileName ));
-        tile->setLastModified( fileInfo.lastModified() );
+    QImage const image( fileName );
+    if ( !image.isNull() ) {
+        tile = QSharedPointer<TextureTile>( new TextureTile( tileId, new QImage( image ) ));
+        tile->setLastModified( QFileInfo( fileName ).lastModified() );
     }
     else {
-        tile = QSharedPointer<TextureTile>( new TextureTile( tileId ));
         QImage * const replacementTile = scaledLowerLevelTile( tileId );
-        if ( replacementTile ) {
-            tile->setImage( replacementTile );
+        tile = QSharedPointer<TextureTile>( new TextureTile( tileId, replacementTile ));
             tile->setState( TextureTile::StateScaled );
         }
-    }
 
     GeoSceneTexture const * const textureLayer = findTextureLayer( tileId );
     tile->setExpireSecs( textureLayer->expire() );
@@ -162,7 +155,11 @@
         return;
     Q_ASSERT( tile );
     m_waitingForUpdate.remove( id );
-    tile->setImage( data );
+    QImage *image( new QImage( QImage::fromData( data ) ) );
+    if ( image->isNull() )
+        return;
+
+    tile->setImage( image );
     tile->setState( TextureTile::StateUptodate );
     tile->setLastModified( QDateTime::currentDateTime() );
     emit tileCompleted( tile->stackedTileId(), id );
@@ -200,17 +197,15 @@
 QImage * TileLoader::scaledLowerLevelTile( TileId const & id )
 {
     mDebug() << "TileLoader::scaledLowerLevelTile" << id.toString();
-    QImage * result = 0;
-    int level = id.zoomLevel() - 1;
-    while ( !result && level >= 0 ) {
+
+    for ( int level = id.zoomLevel() - 1; level >= 0; --level ) {
         int const deltaLevel = id.zoomLevel() - level;
         TileId const replacementTileId( id.mapThemeIdHash(), level,
                                         id.x() >> deltaLevel, id.y() >> deltaLevel );
         mDebug() << "TileLoader::scaledLowerLevelTile" << "trying" << replacementTileId.toString();
         QString const fileName = tileFileName( replacementTileId );
-        QFileInfo const fileInfo( fileName );
-        if ( fileInfo.exists() ) {
             QImage const toScale( fileName );
+        if ( !toScale.isNull() ) {
             // which rect to scale?
             QSize const size = toScale.size();
             int const restTileX = id.x() % ( 1 << deltaLevel );
@@ -222,11 +217,12 @@
             mDebug() << "QImage::copy:" << startX << startY << partWidth << partHeight;
             QImage const part = toScale.copy( startX, startY, partWidth, partHeight );
             mDebug() << "QImage::scaled:" << toScale.size();
-            result = new QImage( part.scaled( toScale.size() ));
+            return new QImage( part.scaled( toScale.size() ) );
         }
-        --level;
     }
-    return result;
+
+    Q_ASSERT_X( false, "scaled image", "level zero image missing" ); // not reached
+    return new QImage();
 }
 
 }


More information about the Marble-commits mailing list