[Marble-devel] RFC: refactoring of tile loading code
Jens-Michael Hoffmann
jensmh at gmx.de
Fri Feb 5 19:44:07 CET 2010
-------------- next part --------------
commit ef1a0883c822d4aff8c5002a3a26c130f8c9e83b
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Fri Feb 5 19:40:08 2010 +0100
Squashed commit of the following:
commit 55496ce15bc8af2d5b312258d6726cc5a6a3c4c7
Merge: b3df354 c11d59e
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Fri Feb 5 19:02:45 2010 +0100
Merge branch 'master' into tileloader-refactoring
commit b3df354fe8894a4ab80a58db641378604d05724a
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Fri Feb 5 18:59:10 2010 +0100
Refactoring of tile loading.
new classes:
- SimpleTextureTile
- SimpleTileLoader
AbstractTile:
- m_created removed, value is derived from the SimpleTextureTiles inside
TextureTile
- setState removed, value is derived from the states of the SimpleTextureTiles
MarbleMap:
- remove handling of clouds on/off, unclear where this should go, was in
MergedLayerDecorator before
MergedLayerDecorator:
- remove handling of clouds, this is now done in a generic way inside
with SimpleTextureTile/TextureTile/TileLoader
- uses now TileLoader instead of instantiating a TextureTile "manually"
TextureTile:
- loadDataset removed
- setImage removed
- now consists of an array of base tiles, which are merged in a result tile (formerly known as rawtile)
- m_forMergedLayerDecorator added
TileLoader:
- loadTile gets special parameter forMergedLayerDecorator
- uses SimpleTileLoader to load the "base" tiles
remaining issues:
- where should "clouds visible" property go?
MarbleModel comes to mind as this is one level above MergeLayerDecorator
- instead of TileLoader::loadTile having the forMergedLayerDecorator parameter
one could think of using SimpleTileLoader inside MergedLayerDecorator
- extend DGML texture element or below with "mergeRule" possible values: Copy, Multiply
commit abb42222ffd1efe93ed9ee22cbe81b5292ab4eab
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Thu Feb 4 21:12:13 2010 +0100
GeoSceneTexture: add method hasMaximumTileLevel().
commit ab099bd50d404ec5dd643c1e29bbe4eb5400454d
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Wed Feb 3 22:43:27 2010 +0100
TileLoaderHelper: we can pass a pointer to a const GeoSceneTexture here.
commit d906b1ee5bf38611f537f18b64a49801d18fc40f
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Wed Feb 3 21:08:53 2010 +0100
TileLoader: remove old updateTile slot, in which the qimage data was read
from the filesystem again instead of using the in-memory copy.
commit be1d1662eda275b2bd1fbc6d60daf6027c784d4a
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Wed Feb 3 20:51:09 2010 +0100
Fix compilation after constness fixes in geodata/scene.
commit 08671eabc1dd48112f409b6bb182dba379c2d8f0
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Wed Feb 3 20:04:34 2010 +0100
Re-add one patch that was committed to master by mistake and then reverted
and now after merging master into this branch, the change was gone here, too.
commit 5731ff84262800a257b788aaf2ce5314e3b153c4
Merge: 35fb787 b72f3ee
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Wed Feb 3 19:50:57 2010 +0100
Merge branch 'master' into tileloader-refactoring
commit b72f3ee374c89cad2e9fe89dac27a9d23467b70d
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 15:43:31 2010 +0100
Revert "TileLoader: add MapThemeManager parameter to constructor."
This reverts commit d550f4a1257d7e0351f51b6e5e4f21faef077304,
because it was committed to the wrong branch.
commit 74c04275c68a43f9a7e63365ad1df6bab562c4be
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 15:35:10 2010 +0100
TileLoader: add MapThemeManager parameter to constructor.
commit 35fb787bcd3c27924f94336d99324a8b7c815e13
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 15:43:31 2010 +0100
Revert "TileLoader: add MapThemeManager parameter to constructor."
This reverts commit d550f4a1257d7e0351f51b6e5e4f21faef077304,
because it was committed to the wrong branch.
commit 51992ff7cccf6332d9dde8de57c4c4836cf2f9f2
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Wed Feb 3 18:18:52 2010 +0100
MergedLayerDecorator: use TileLoader instead of maunally instanciating a
TextureTile and then calling textureTile::loadDataset.
In order to prevent infinite recursion, there is a (hard coded) check in
TileLoader::mergeDecorations to prevent this (half heartedly).
Loading/displaying of clouds layer if cloud tiles are not available locally
remains broken.
commit 753571e6708892a867ce0d69f6ac3267ad2ebc81
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 22:03:46 2010 +0100
TileLoader::initTextureLayers: find really all texture layers.
A map theme may have (and in fact some do) several texture layers, so
we have to iterate through all layers to find them.
commit 5f7b580041141d9add5921e091f57151caced8ad
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 20:58:06 2010 +0100
TileLoader: remove setLayer method and corresponding data member.
commit 1f3bb64dda957e6a1d1ec859d05adb1ba98e0aa2
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 20:50:03 2010 +0100
TileLoader: make maximumTileLevel() static again and add texture layer parameter.
This way the texture layer can be removed from TileLoader's state.
The parameter of TileLoaderHelp::themeStr() had to be constified for this to compile.
commit 6d6cce8233fe23cff423a05f94e937b7140de5d8
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 20:24:34 2010 +0100
TileLoader: remove methods tileWidth() and tileHeight().
The result of these methods depend on a given texture layer. As TileLoader's
state should not contain a texture layer, move this to
AbstractScanlineTextureMapper. A different possibility would have been to
add a GeoSceneTexture parameter, but since these methods are not part of
the tile loading core business, but more convenience methods for
the texture mappers, I like it more this way.
commit d29a8f124b037d36e3a2d3b6c085a0383d26a0a3
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 19:29:31 2010 +0100
TileLoader: remove unused signal paintTile.
commit e64b2c3f723a8b7bf34afe29800a02e387c5a5af
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 19:12:20 2010 +0100
TileLoader: switch updateTile methods from using the current texture layer
over to the hash of texture layers and use the given TileId to select.
commit 19eb773a47e07f8845d166f6e35b9e9d2b5dcaac
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 19:00:22 2010 +0100
TileLoader: remove methods globalWidth() and globalHeight().
As these methods depend on thew current texture layer and
AbstractScanlineTextureMapper was the only user of these methods,
move them there.
commit 0b809a47b1f98e8772e36bdb125ee93a46db54ec
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 18:17:57 2010 +0100
TileLoader: remove method layer() which returns the current texture layer.
The current texture layer should not be part of TileLoader's state. So
as a step towards the removal of this, remove method layer() which returns
it and switch users of TileLoader::layer() over to alternatives.
commit 80ff4a725341e4affe790733f41b3602f91eb3b4
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 17:26:05 2010 +0100
TileLoader::loadTile: switch over to new internal hash of texture layers.
commit bb84daf3df1bd29f7c5f4b9a849da5daa31224d8
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 16:37:34 2010 +0100
TileLoader: add hash with texture layers.
commit 0652a52d7a544b6ce848f716dba13a1fc7239df7
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 15:47:12 2010 +0100
Remove extra empty line.
commit a5ab1f1d5f3d17594c228812d6464906eebcb5c6
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 15:35:10 2010 +0100
TileLoader: add MapThemeManager parameter to constructor.
commit a9356a9450d6d26a91c5e2910315f305ce1dd7b8
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 15:21:00 2010 +0100
MapThemeManager: add method mapThemes() which returns all map themes.
commit 34e629a4f4854550b173c2115fe78b18711bd8cc
Author: Jens-Michael Hoffmann <jensmh at gmx.de>
Date: Mon Feb 1 13:24:00 2010 +0100
TileId: add map theme id, needed do identify tiles across different map themes.
This change breaks the cloudes layer again, this time it is because clouds
rendering relies on TileLoader::updateTile triggering MarbleModel::paintTile,
which is only done if the tile is found to be currently displayed, which is
true for the underlying tile of the bluemarble theme, but not for the
cloud tile. Now that TileId contains the map theme id, the cloud tile
is no longer recognized as the bluemarble tile.
diff --git a/marble/src/lib/AbstractScanlineTextureMapper.cpp b/marble/src/lib/AbstractScanlineTextureMapper.cpp
index 5f59286..849f56b 100644
--- a/marble/src/lib/AbstractScanlineTextureMapper.cpp
+++ b/marble/src/lib/AbstractScanlineTextureMapper.cpp
@@ -10,6 +10,8 @@
#include "AbstractScanlineTextureMapper.h"
+#include <QtGui/QImage>
+
#include "MarbleDebug.h"
#include "TextureTile.h"
#include "TileId.h"
@@ -20,7 +22,9 @@
using namespace Marble;
-AbstractScanlineTextureMapper::AbstractScanlineTextureMapper( TileLoader *tileLoader, QObject * parent )
+AbstractScanlineTextureMapper::AbstractScanlineTextureMapper( GeoSceneTexture *textureLayer,
+ TileLoader *tileLoader,
+ QObject *parent )
: QObject( parent ),
m_interpolate( false ),
m_maxGlobalX( 0 ),
@@ -32,6 +36,7 @@ AbstractScanlineTextureMapper::AbstractScanlineTextureMapper( TileLoader *tileLo
m_toTileCoordinatesLon( 0.0 ),
m_toTileCoordinatesLat( 0.0 ),
m_interlaced( false ),
+ m_textureLayer( textureLayer ),
m_tileLoader( tileLoader ),
m_tile( 0 ),
m_tileLevel( 0 ),
@@ -42,42 +47,34 @@ AbstractScanlineTextureMapper::AbstractScanlineTextureMapper( TileLoader *tileLo
m_globalWidth( 0 ),
m_globalHeight( 0 ),
m_normGlobalWidth( 0.0 ),
- m_normGlobalHeight( 0.0 )
+ m_normGlobalHeight( 0.0 ),
+ m_mapThemeIdHash( textureLayer ? qHash( textureLayer->sourceDir() ) : 0 )
{
- GeoSceneTexture * texture = 0;
-
- if ( tileLoader ) {
- GeoSceneLayer * layer = tileLoader->layer();
- if ( layer ) {
- texture = static_cast<GeoSceneTexture *>( layer->groundDataset() );
- }
- }
-
- m_tileProjection = tileLoader && texture
- ? texture->projection()
- : GeoSceneTexture::Equirectangular;
+ m_tileProjection = textureLayer ? textureLayer->projection()
+ : GeoSceneTexture::Equirectangular;
connect( m_tileLoader, SIGNAL( tileUpdateAvailable() ),
this, SLOT( notifyMapChanged() ) );
detectMaxTileLevel();
+ initTileSize();
}
AbstractScanlineTextureMapper::~AbstractScanlineTextureMapper()
{
m_tileLoader->disconnect();
-// delete m_tileLoader;
}
void AbstractScanlineTextureMapper::setLayer( GeoSceneLayer * layer )
{
- m_tileLoader->setLayer( layer );
- GeoSceneTexture * texture = static_cast<GeoSceneTexture *>( layer->groundDataset() );
- m_tileProjection = texture->projection();
+ m_textureLayer = static_cast<GeoSceneTexture *>( layer->groundDataset() );
+ m_tileProjection = m_textureLayer->projection();
+ m_mapThemeIdHash = qHash( m_textureLayer->sourceDir() );
m_tileLevel = -1;
detectMaxTileLevel();
+ initTileSize();
}
@@ -89,7 +86,7 @@ void AbstractScanlineTextureMapper::selectTileLevel( ViewParams* viewParams )
// the tile level from tilesize and the globe radius via log(2)
qreal linearLevel = ( 2.0 * (qreal)( radius )
- / (qreal) ( m_tileLoader->tileWidth() ) );
+ / (qreal) ( m_tileSize.width() ) );
int tileLevel = 0;
if ( linearLevel < 1.0 )
@@ -115,9 +112,9 @@ void AbstractScanlineTextureMapper::tileLevelInit( int tileLevel )
// mDebug() << "Texture Level was set to: " << tileLevel;
m_tileLevel = tileLevel;
- m_globalWidth = m_tileLoader->globalWidth( m_tileLevel );
+ initGlobalWidth();
m_normGlobalWidth = (qreal)( m_globalWidth / ( 2 * M_PI ) );
- m_globalHeight = m_tileLoader->globalHeight( m_tileLevel );
+ initGlobalHeight();
m_normGlobalHeight = (qreal)( m_globalHeight / M_PI );
m_maxGlobalX = m_globalWidth - 1;
@@ -170,9 +167,9 @@ void AbstractScanlineTextureMapper::pixelValueF(qreal lon,
// same tile. However at the tile border we might "fall off". If that
// happens we need to find out the next tile that needs to be loaded.
- if ( posX >= (qreal)( m_tileLoader->tileWidth() )
+ if ( posX >= (qreal)( m_tileSize.width() )
|| posX < 0.0
- || posY >= (qreal)( m_tileLoader->tileHeight() )
+ || posY >= (qreal)( m_tileSize.height() )
|| posY < 0.0 )
{
nextTile( posX, posY );
@@ -203,9 +200,9 @@ void AbstractScanlineTextureMapper::pixelValue(qreal lon,
// same tile. However at the tile border we might "fall off". If that
// happens we need to find out the next tile that needs to be loaded.
- if ( iPosX >= m_tileLoader->tileWidth()
+ if ( iPosX >= m_tileSize.width()
|| iPosX < 0
- || iPosY >= m_tileLoader->tileHeight()
+ || iPosY >= m_tileSize.height()
|| iPosY < 0 )
{
nextTile( iPosX, iPosY );
@@ -257,8 +254,8 @@ void AbstractScanlineTextureMapper::pixelValueApproxF(const qreal& lon,
qreal itLon = m_prevLon + m_toTileCoordinatesLon;
qreal itLat = m_prevLat + m_toTileCoordinatesLat;
- const int tileWidth = m_tileLoader->tileWidth();
- const int tileHeight = m_tileLoader->tileHeight();
+ const int tileWidth = m_tileSize.width();
+ const int tileHeight = m_tileSize.height();
// int oldR = 0;
// int oldG = 0;
@@ -401,8 +398,8 @@ void AbstractScanlineTextureMapper::pixelValueApprox(const qreal& lon,
int itLon = (int)( ( m_prevLon + m_toTileCoordinatesLon ) * 128.0 );
int itLat = (int)( ( m_prevLat + m_toTileCoordinatesLat ) * 128.0 );
- const int tileWidth = m_tileLoader->tileWidth();
- const int tileHeight = m_tileLoader->tileHeight();
+ const int tileWidth = m_tileSize.width();
+ const int tileHeight = m_tileSize.height();
const bool alwaysCheckTileRange =
isOutOfTileRange( itLon, itLat, itStepLon, itStepLat,
@@ -529,21 +526,21 @@ void AbstractScanlineTextureMapper::nextTile( int &posX, int &posY )
// tileCol counts the tile columns left from the current tile.
// tileRow counts the tile rows on the top from the current tile.
- int tileCol = lon / m_tileLoader->tileWidth();
- int tileRow = lat / m_tileLoader->tileHeight();
+ int tileCol = lon / m_tileSize.width();
+ int tileRow = lat / m_tileSize.height();
- m_tile = m_tileLoader->loadTile( TileId( m_tileLevel, tileCol, tileRow ));
+ m_tile = m_tileLoader->loadTile( TileId( m_mapThemeIdHash, m_tileLevel, tileCol, tileRow ));
// Update position variables:
// m_tilePosX/Y stores the position of the tiles in
// global texture coordinates
// ( origin upper left, measured in pixels )
- m_tilePosX = tileCol * m_tileLoader->tileWidth();
+ m_tilePosX = tileCol * m_tileSize.width();
m_toTileCoordinatesLon = (qreal)(m_globalWidth / 2 - m_tilePosX);
posX = lon - m_tilePosX;
- m_tilePosY = tileRow * m_tileLoader->tileHeight();
+ m_tilePosY = tileRow * m_tileSize.height();
m_toTileCoordinatesLat = (qreal)(m_globalHeight / 2 - m_tilePosY);
posY = lat - m_tilePosY;
}
@@ -564,21 +561,21 @@ void AbstractScanlineTextureMapper::nextTile( qreal &posX, qreal &posY )
// tileCol counts the tile columns left from the current tile.
// tileRow counts the tile rows on the top from the current tile.
- int tileCol = lon / m_tileLoader->tileWidth();
- int tileRow = lat / m_tileLoader->tileHeight();
+ int tileCol = lon / m_tileSize.width();
+ int tileRow = lat / m_tileSize.height();
- m_tile = m_tileLoader->loadTile( TileId( m_tileLevel, tileCol, tileRow ));
+ m_tile = m_tileLoader->loadTile( TileId( m_mapThemeIdHash, m_tileLevel, tileCol, tileRow ));
// Update position variables:
// m_tilePosX/Y stores the position of the tiles in
// global texture coordinates
// ( origin upper left, measured in pixels )
- m_tilePosX = tileCol * m_tileLoader->tileWidth();
+ m_tilePosX = tileCol * m_tileSize.width();
m_toTileCoordinatesLon = (qreal)(m_globalWidth / 2 - m_tilePosX);
posX = lon - m_tilePosX;
- m_tilePosY = tileRow * m_tileLoader->tileHeight();
+ m_tilePosY = tileRow * m_tileSize.height();
m_toTileCoordinatesLat = (qreal)(m_globalHeight / 2 - m_tilePosY);
posY = lat - m_tilePosY;
}
@@ -586,14 +583,39 @@ void AbstractScanlineTextureMapper::nextTile( qreal &posX, qreal &posY )
void AbstractScanlineTextureMapper::notifyMapChanged()
{
detectMaxTileLevel();
-// mDebug() << "MAPCHANGED";
+ //mDebug() << "AbstractScanlineTextureMapper: emitting mapChanged";
emit mapChanged();
}
void AbstractScanlineTextureMapper::detectMaxTileLevel()
{
- m_maxTileLevel = m_tileLoader->maximumTileLevel();
+ m_maxTileLevel = TileLoader::maximumTileLevel( m_textureLayer );
// mDebug() << "MaxTileLevel: " << m_maxTileLevel;
}
+void AbstractScanlineTextureMapper::initGlobalWidth()
+{
+ m_globalWidth = m_tileSize.width()
+ * TileLoaderHelper::levelToColumn( m_textureLayer->levelZeroColumns(), m_tileLevel );
+}
+
+void AbstractScanlineTextureMapper::initGlobalHeight()
+{
+ m_globalHeight = m_tileSize.height()
+ * TileLoaderHelper::levelToRow( m_textureLayer->levelZeroRows(), m_tileLevel );
+}
+
+void AbstractScanlineTextureMapper::initTileSize()
+{
+ if ( !m_textureLayer || !m_tileLoader )
+ return;
+
+ Q_ASSERT( m_textureLayer );
+ Q_ASSERT( m_tileLoader );
+ TileId id( m_textureLayer->sourceDir(), 0, 0, 0 );
+ TextureTile * const testTile = m_tileLoader->loadTile( id );
+ Q_ASSERT( testTile );
+ m_tileSize = testTile->rawtile().size();
+}
+
#include "AbstractScanlineTextureMapper.moc"
diff --git a/marble/src/lib/AbstractScanlineTextureMapper.h b/marble/src/lib/AbstractScanlineTextureMapper.h
index 81e88f5..1f3e763 100644
--- a/marble/src/lib/AbstractScanlineTextureMapper.h
+++ b/marble/src/lib/AbstractScanlineTextureMapper.h
@@ -13,6 +13,7 @@
#define ABSTRACTSCANLINETEXTUREMAPPER_H
#include <QtCore/QObject>
+#include <QtCore/QSize>
#include <QtGui/QColor>
#include <cmath>
@@ -35,7 +36,8 @@ class AbstractScanlineTextureMapper : public QObject
Q_OBJECT
public:
- explicit AbstractScanlineTextureMapper( TileLoader *tileLoader, QObject * parent=0 );
+ AbstractScanlineTextureMapper( GeoSceneTexture *textureLayer, TileLoader *tileLoader,
+ QObject *parent = 0 );
~AbstractScanlineTextureMapper();
virtual void mapTexture( ViewParams *viewParams ) = 0;
@@ -121,6 +123,9 @@ public:
// ------------------------
// Tile stuff
+ GeoSceneTexture *m_textureLayer;
+ /// size of the tiles of of the current texture layer
+ QSize m_tileSize;
TileLoader *m_tileLoader;
GeoSceneTexture::Projection m_tileProjection;
@@ -142,10 +147,15 @@ public:
private:
Q_DISABLE_COPY( AbstractScanlineTextureMapper )
+ void initGlobalWidth();
+ void initGlobalHeight();
+ void initTileSize();
+
int m_globalWidth;
int m_globalHeight;
qreal m_normGlobalWidth;
qreal m_normGlobalHeight;
+ uint m_mapThemeIdHash;
};
inline void AbstractScanlineTextureMapper::setMaxTileLevel( int level )
diff --git a/marble/src/lib/AbstractTile.cpp b/marble/src/lib/AbstractTile.cpp
index b38bff3..f0ac99d 100644
--- a/marble/src/lib/AbstractTile.cpp
+++ b/marble/src/lib/AbstractTile.cpp
@@ -13,8 +13,6 @@
#include "AbstractTile.h"
#include "AbstractTile_p.h"
-#include <QtCore/QDateTime>
-
#include "TileId.h"
namespace Marble
@@ -23,8 +21,7 @@ namespace Marble
AbstractTilePrivate::AbstractTilePrivate( const TileId& id )
: m_id( id ),
m_used( false ),
- m_state( AbstractTile::TileEmpty ),
- m_created( QDateTime::currentDateTime() )
+ m_state( AbstractTile::TileEmpty )
{
}
@@ -72,24 +69,6 @@ AbstractTile::TileState AbstractTile::state() const
return d->m_state;
}
-void AbstractTile::setState( TileState state )
-{
- Q_D( AbstractTile );
- d->m_state = state;
-}
-
-const QDateTime & AbstractTile::created() const
-{
- Q_D( const AbstractTile );
- return d->m_created;
-}
-
-void AbstractTile::setCreated( const QDateTime &created )
-{
- Q_D( AbstractTile );
- d->m_created = created;
-}
-
}
#include "AbstractTile.moc"
diff --git a/marble/src/lib/AbstractTile.h b/marble/src/lib/AbstractTile.h
index a43124a..93275b4 100644
--- a/marble/src/lib/AbstractTile.h
+++ b/marble/src/lib/AbstractTile.h
@@ -56,10 +56,6 @@ class AbstractTile : public QObject
void setUsed( bool used );
TileState state() const;
- void setState( TileState state );
-
- const QDateTime & created() const;
- void setCreated( const QDateTime &created );
protected:
AbstractTilePrivate * const d_ptr;
diff --git a/marble/src/lib/AbstractTile_p.h b/marble/src/lib/AbstractTile_p.h
index 40c63dd..787a17c 100644
--- a/marble/src/lib/AbstractTile_p.h
+++ b/marble/src/lib/AbstractTile_p.h
@@ -12,19 +12,14 @@
// Description: AbstractTile contains the base class for a single quadtile
//
-
#ifndef MARBLE_ABSTRACTTILE_P_H
#define MARBLE_ABSTRACTTILE_P_H
-#include <QtCore/QDateTime>
-
#include "TileId.h"
-
namespace Marble
{
-
class AbstractTilePrivate
{
public:
@@ -35,8 +30,6 @@ class AbstractTilePrivate
bool m_used;
AbstractTile::TileState m_state;
- QDateTime m_created;
-
AbstractTile * q_ptr;
};
diff --git a/marble/src/lib/CMakeLists.txt b/marble/src/lib/CMakeLists.txt
index 80a7cd9..19abc18 100644
--- a/marble/src/lib/CMakeLists.txt
+++ b/marble/src/lib/CMakeLists.txt
@@ -74,7 +74,8 @@ set(marblewidget_SRCS
MarbleGeometryModel.cpp
MarbleDataFacade.cpp
MarbleDebug.cpp
-
+ SimpleTextureTile.cpp
+ SimpleTileLoader.cpp
QtMarbleConfigDialog.cpp
ClipPainter.cpp
DownloadPolicy.cpp
diff --git a/marble/src/lib/EquirectScanlineTextureMapper.cpp b/marble/src/lib/EquirectScanlineTextureMapper.cpp
index 979272a..7d114ea 100644
--- a/marble/src/lib/EquirectScanlineTextureMapper.cpp
+++ b/marble/src/lib/EquirectScanlineTextureMapper.cpp
@@ -29,9 +29,10 @@
using namespace Marble;
-EquirectScanlineTextureMapper::EquirectScanlineTextureMapper( TileLoader *tileLoader,
- QObject * parent )
- : AbstractScanlineTextureMapper( tileLoader, parent ),
+EquirectScanlineTextureMapper::EquirectScanlineTextureMapper( GeoSceneTexture *textureLayer,
+ TileLoader *tileLoader,
+ QObject *parent )
+ : AbstractScanlineTextureMapper( textureLayer, tileLoader, parent ),
m_oldCenterLon( 0.0 ),
m_oldYPaintedTop( 0 )
{
diff --git a/marble/src/lib/EquirectScanlineTextureMapper.h b/marble/src/lib/EquirectScanlineTextureMapper.h
index 8d11081..bc13f17 100644
--- a/marble/src/lib/EquirectScanlineTextureMapper.h
+++ b/marble/src/lib/EquirectScanlineTextureMapper.h
@@ -24,8 +24,8 @@ class EquirectScanlineTextureMapper : public AbstractScanlineTextureMapper
Q_OBJECT
public:
- explicit EquirectScanlineTextureMapper( TileLoader *tileLoader,
- QObject *parent = 0 );
+ EquirectScanlineTextureMapper( GeoSceneTexture *textureLayer, TileLoader *tileLoader,
+ QObject *parent = 0 );
void mapTexture( ViewParams *viewParams );
private:
diff --git a/marble/src/lib/MapThemeManager.cpp b/marble/src/lib/MapThemeManager.cpp
index 65aad98..27381e8 100644
--- a/marble/src/lib/MapThemeManager.cpp
+++ b/marble/src/lib/MapThemeManager.cpp
@@ -75,6 +75,18 @@ MapThemeManager::~MapThemeManager()
delete d;
}
+QList<GeoSceneDocument const*> MapThemeManager::mapThemes() const
+{
+ QList<GeoSceneDocument const*> result;
+ const QStringList mapThemes = findMapThemes();
+ QStringList::const_iterator pos = mapThemes.constBegin();
+ QStringList::const_iterator const end = mapThemes.constEnd();
+ for (; pos != end; ++pos ) {
+ result.append( loadMapTheme( *pos ));
+ }
+ return result;
+}
+
void MapThemeManager::initialize()
{
initFileSystemWatcher();
diff --git a/marble/src/lib/MapThemeManager.h b/marble/src/lib/MapThemeManager.h
index c4d433b..3cd0de5 100644
--- a/marble/src/lib/MapThemeManager.h
+++ b/marble/src/lib/MapThemeManager.h
@@ -55,7 +55,12 @@ class MARBLE_EXPORT MapThemeManager : public QObject
public:
explicit MapThemeManager(QObject *parent = 0);
~MapThemeManager();
-
+
+ /**
+ * @brief Returns a list of all locally available map themes
+ */
+ QList<GeoSceneDocument const*> mapThemes() const;
+
/**
* @brief Provides a model of the locally existing themes.
*
diff --git a/marble/src/lib/MarbleMap.cpp b/marble/src/lib/MarbleMap.cpp
index b449bb7..196dbf5 100644
--- a/marble/src/lib/MarbleMap.cpp
+++ b/marble/src/lib/MarbleMap.cpp
@@ -635,7 +635,8 @@ bool MarbleMap::showGrid() const
bool MarbleMap::showClouds() const
{
- return d->m_model->layerDecorator()->showClouds();
+ // TODO
+ return true;
}
bool MarbleMap::showAtmosphere() const
@@ -1034,15 +1035,9 @@ void MarbleMap::setShowCrosshairs( bool visible )
void MarbleMap::setShowClouds( bool visible )
{
- bool previousVisible = d->m_model->layerDecorator()->showClouds();
-
- d->m_model->layerDecorator()->setShowClouds( visible );
-
- if ( previousVisible != visible ) {
- mDebug() << "Changing cloud layer";
- d->m_model->update();
- }
+ // TODO
}
+
void MarbleMap::setShowTileId( bool visible )
{
diff --git a/marble/src/lib/MarbleModel.cpp b/marble/src/lib/MarbleModel.cpp
index 8aff1a0..77528a6 100644
--- a/marble/src/lib/MarbleModel.cpp
+++ b/marble/src/lib/MarbleModel.cpp
@@ -23,6 +23,7 @@
#include <QtGui/QItemSelectionModel>
#include <QtGui/QSortFilterProxyModel>
+#include "MapThemeManager.h"
#include "global.h"
#include "MarbleDebug.h"
#include "gps/GpsLayer.h"
@@ -86,6 +87,7 @@ class MarbleModelPrivate
: m_parent( parent ),
m_dataFacade( 0 ),
m_pluginManager( new PluginManager( parent ) ),
+ m_mapThemeManager( new MapThemeManager( parent )),
m_mapTheme( 0 ),
m_layerManager( 0 ),
m_downloadManager( new HttpDownloadManager( new FileStoragePolicy(
@@ -109,6 +111,7 @@ class MarbleModelPrivate
MarbleDataFacade *m_dataFacade;
PluginManager *m_pluginManager;
+ MapThemeManager *m_mapThemeManager;
// View and paint stuff
GeoSceneDocument *m_mapTheme;
@@ -161,7 +164,7 @@ MarbleModel::MarbleModel( QObject *parent )
d->m_downloadManager, SLOT( addJob( QUrl, QString, QString, DownloadUsage )));
d->m_dataFacade = new MarbleDataFacade( this );
- d->m_tileLoader = new TileLoader( d->m_downloadManager, this );
+ d->m_tileLoader = new TileLoader( d->m_mapThemeManager, d->m_downloadManager, this );
d->m_texmapper = 0;
@@ -224,7 +227,7 @@ MarbleModel::MarbleModel( QObject *parent )
/* Assume we are dealing with the earth */
d->m_planet = new Planet( "earth" );
d->m_sunLocator = new SunLocator( d->m_dateTime, d->m_planet );
- d->m_layerDecorator = new MergedLayerDecorator( d->m_sunLocator );
+ d->m_layerDecorator = new MergedLayerDecorator( d->m_tileLoader, d->m_sunLocator );
connect(d->m_dateTime, SIGNAL( timeChanged() ),
d->m_sunLocator, SLOT( update() ) );
@@ -371,7 +374,6 @@ void MarbleModel::setMapTheme( GeoSceneDocument* mapTheme,
qDebug("Tile creation completed");
delete tileCreatorDlg;
}
- d->m_tileLoader->setLayer( layer );
}
else {
d->m_tileLoader->flush();
@@ -496,18 +498,20 @@ void MarbleModel::setMapTheme( GeoSceneDocument* mapTheme,
void MarbleModel::setupTextureMapper( Projection projection )
{
// FIXME: replace this with an approach based on the factory method pattern.
-
delete d->m_texmapper;
switch( projection ) {
case Spherical:
- d->m_texmapper = new SphericalScanlineTextureMapper( d->m_tileLoader, this );
+ d->m_texmapper = new SphericalScanlineTextureMapper( textureLayer(), d->m_tileLoader,
+ this );
break;
case Equirectangular:
- d->m_texmapper = new EquirectScanlineTextureMapper( d->m_tileLoader, this );
+ d->m_texmapper = new EquirectScanlineTextureMapper( textureLayer(), d->m_tileLoader,
+ this );
break;
case Mercator:
- d->m_texmapper = new MercatorScanlineTextureMapper( d->m_tileLoader, this );
+ d->m_texmapper = new MercatorScanlineTextureMapper( textureLayer(), d->m_tileLoader,
+ this );
break;
}
@@ -838,11 +842,6 @@ void MarbleModel::paintTile( TextureTile* tile, GeoSceneTexture *textureLayer )
{
// mDebug() << "MarbleModel::paintTile: " << "x: " << x << "y:" << y << "level: " << level
// << "requestTileUpdate" << requestTileUpdate;
-
- if ( d->m_downloadManager != 0 ) {
- connect( d->m_layerDecorator, SIGNAL( downloadTile( QUrl, QString, QString, DownloadUsage ) ),
- d->m_downloadManager, SLOT( addJob( QUrl, QString, QString, DownloadUsage ) ) );
- }
d->m_layerDecorator->setInfo( tile->id() );
d->m_layerDecorator->setTile( tile->tile() );
@@ -939,6 +938,23 @@ void MarbleModel::addDownloadPolicies( GeoSceneDocument *mapTheme )
}
}
+GeoSceneTexture * MarbleModel::textureLayer() const
+{
+ if ( !d->m_mapTheme )
+ return 0;
+ if ( !d->m_mapTheme->map()->hasTextureLayers() )
+ return 0;
+
+ // As long as we don't have an Layer Management Class we just lookup
+ // the name of the layer that has the same name as the theme Id
+ const QString themeId = d->m_mapTheme->head()->theme();
+ GeoSceneLayer * const layer = static_cast<GeoSceneLayer*>( d->m_mapTheme->map()->layer( themeId ));
+ if ( !layer )
+ return 0;
+
+ return static_cast<GeoSceneTexture*>( layer->groundDataset() );
+}
+
}
#include "MarbleModel.moc"
diff --git a/marble/src/lib/MarbleModel.h b/marble/src/lib/MarbleModel.h
index b4c720d..4888088 100644
--- a/marble/src/lib/MarbleModel.h
+++ b/marble/src/lib/MarbleModel.h
@@ -368,6 +368,7 @@ class MARBLE_EXPORT MarbleModel : public QObject
Q_PRIVATE_SLOT( d, void notifyModelChanged() )
void addDownloadPolicies( GeoSceneDocument *mapTheme );
+ GeoSceneTexture * textureLayer() const;
MarbleModelPrivate * const d;
};
diff --git a/marble/src/lib/MercatorScanlineTextureMapper.cpp b/marble/src/lib/MercatorScanlineTextureMapper.cpp
index deaa1af..27cbf20 100644
--- a/marble/src/lib/MercatorScanlineTextureMapper.cpp
+++ b/marble/src/lib/MercatorScanlineTextureMapper.cpp
@@ -31,9 +31,10 @@
using namespace Marble;
-MercatorScanlineTextureMapper::MercatorScanlineTextureMapper( TileLoader *tileLoader,
- QObject * parent )
- : AbstractScanlineTextureMapper( tileLoader, parent ),
+MercatorScanlineTextureMapper::MercatorScanlineTextureMapper( GeoSceneTexture *textureLayer,
+ TileLoader *tileLoader,
+ QObject *parent )
+ : AbstractScanlineTextureMapper( textureLayer, tileLoader, parent ),
m_oldCenterLon( 0.0 ),
m_oldYPaintedTop( 0 )
{
diff --git a/marble/src/lib/MercatorScanlineTextureMapper.h b/marble/src/lib/MercatorScanlineTextureMapper.h
index 8661c43..15e26c5 100644
--- a/marble/src/lib/MercatorScanlineTextureMapper.h
+++ b/marble/src/lib/MercatorScanlineTextureMapper.h
@@ -24,8 +24,8 @@ class MercatorScanlineTextureMapper : public AbstractScanlineTextureMapper
Q_OBJECT
public:
- explicit MercatorScanlineTextureMapper( TileLoader *tileLoader,
- QObject *parent = 0 );
+ MercatorScanlineTextureMapper( GeoSceneTexture *textureLayer, TileLoader *tileLoader,
+ QObject *parent = 0 );
void mapTexture( ViewParams *viewParams );
private:
diff --git a/marble/src/lib/MergedLayerDecorator.cpp b/marble/src/lib/MergedLayerDecorator.cpp
index 2ae96d8..18f5d23 100644
--- a/marble/src/lib/MergedLayerDecorator.cpp
+++ b/marble/src/lib/MergedLayerDecorator.cpp
@@ -20,6 +20,7 @@
#include <QtGui/QPainter>
#include "SunLocator.h"
+#include "TileLoader.h"
#include "global.h"
#include "MarbleDebug.h"
#include "GeoSceneDocument.h"
@@ -34,34 +35,17 @@
using namespace Marble;
-MergedLayerDecorator::MergedLayerDecorator(SunLocator* sunLocator)
- : m_tile( 0 ),
+MergedLayerDecorator::MergedLayerDecorator( TileLoader * const tileLoader, SunLocator* sunLocator )
+ : m_tileLoader( tileLoader ),
+ m_tile( 0 ),
m_id(),
m_sunLocator( sunLocator ),
- m_cloudlayer( false ),
m_showTileId( false ),
m_cityLightsTheme( 0 ),
- m_blueMarbleTheme( 0 ),
- m_cityLightsTextureLayer( 0 ),
- m_cloudsTextureLayer( 0 )
+ m_cityLightsTextureLayer( 0 )
{
}
-void MergedLayerDecorator::initClouds()
-{
- // look for the texture layers inside the themes
- // As long as we don't have an Layer Management Class we just lookup
- // the name of the layer that has the same name as the theme ID
-
- // the clouds texture layer is a layer in the bluemarble theme
- m_blueMarbleTheme = MapThemeManager::loadMapTheme( "earth/bluemarble/bluemarble.dgml" );
- if ( m_blueMarbleTheme ) {
- QString blueMarbleId = m_blueMarbleTheme->head()->theme();
- m_cloudsTextureLayer = static_cast<GeoSceneTexture*>(
- m_blueMarbleTheme->map()->layer( blueMarbleId )->dataset( "clouds_data" ) );
- }
-}
-
void MergedLayerDecorator::initCityLights()
{
// look for the texture layers inside the themes
@@ -80,7 +64,6 @@ void MergedLayerDecorator::initCityLights()
MergedLayerDecorator::~MergedLayerDecorator()
{
delete m_cityLightsTheme;
- delete m_blueMarbleTheme;
}
void MergedLayerDecorator::paint( const QString& themeId, GeoSceneDocument *mapTheme )
@@ -88,17 +71,6 @@ void MergedLayerDecorator::paint( const QString& themeId, GeoSceneDocument *mapT
// QTime time;
// time.start();
- if ( m_cloudlayer && m_tile->depth() == 32 && m_id.zoomLevel() < 2 ) {
- bool show;
- if ( mapTheme && mapTheme->settings()->propertyAvailable( "clouds", show ) ) {
-
- // Initialize clouds if it hasn't happened already
- if ( !m_blueMarbleTheme ) {
- initClouds();
- }
- paintClouds();
- }
- }
if ( m_sunLocator->getShow() && mapTheme ) {
// Initialize citylights layer if it hasn't happened already
@@ -114,16 +86,6 @@ void MergedLayerDecorator::paint( const QString& themeId, GeoSceneDocument *mapT
}
}
-void MergedLayerDecorator::setShowClouds( bool visible )
-{
- m_cloudlayer = visible;
-}
-
-bool MergedLayerDecorator::showClouds() const
-{
- return m_cloudlayer;
-}
-
void MergedLayerDecorator::setShowTileId( bool visible )
{
m_showTileId = visible;
@@ -134,59 +96,12 @@ bool MergedLayerDecorator::showTileId() const
return m_showTileId;
}
-QImage MergedLayerDecorator::loadDataset( GeoSceneTexture *textureLayer )
-{
- // TODO use a TileLoader rather than directly accessing TextureTile?
- TextureTile tile( m_id );
-
- connect( &tile, SIGNAL( downloadTile( const QUrl&, const QString&, const QString&, DownloadUsage ) ),
- this, SIGNAL( downloadTile( const QUrl&, const QString&, const QString&, DownloadUsage ) ) );
-
- tile.loadDataset( textureLayer );
- return *( tile.tile() );
-}
-
-void MergedLayerDecorator::paintClouds()
+TextureTile * MergedLayerDecorator::loadDataset( GeoSceneTexture *textureLayer )
{
- QImage cloudtile = loadDataset( m_cloudsTextureLayer );
- if ( cloudtile.isNull() )
- return;
-
- // Do not attempt to paint clouds if cloud tile and map tile have
- // got different sizes.
- // FIXME: make cloud a separate texture layer
- if ( cloudtile.height() != m_tile->height() || cloudtile.width() != m_tile->width() )
- return;
-
-// mDebug() << "cloud tile:" << cloudtile.height() << cloudtile.width() << cloudtile.depth()
-// << " map tile:" << m_tile->height() << m_tile->width() << m_tile->depth();
-
- const int ctileHeight = cloudtile.height();
- const int ctileWidth = cloudtile.width();
-
- for ( int cur_y = 0; cur_y < ctileHeight; ++cur_y ) {
- uchar *cscanline = (uchar*)cloudtile.scanLine( cur_y );
- QRgb *scanline = (QRgb*)m_tile->scanLine( cur_y );
- for ( int cur_x = 0; cur_x < ctileWidth; ++cur_x ) {
- qreal c;
- if ( cloudtile.depth() == 32)
- c = qRed( *((QRgb*)cscanline) ) / 255.0;
- else
- c = *cscanline / 255.0;
- QRgb pix = *scanline;
- int r = qRed( pix );
- int g = qGreen( pix );
- int b = qBlue( pix );
- *scanline = qRgb( (int)( r + (255-r)*c ),
- (int)( g + (255-g)*c ),
- (int)( b + (255-b)*c ) );
- if ( cloudtile.depth() == 32)
- cscanline += sizeof( QRgb );
- else
- cscanline++;
- scanline++;
- }
- }
+ const TileId decorationTileId( textureLayer->sourceDir(), m_id.zoomLevel(), m_id.x(), m_id.y());
+ TextureTile * const tile = m_tileLoader->loadTile( decorationTileId, true );
+ tile->setUsed( true );
+ return tile;
}
void MergedLayerDecorator::paintSunShading()
@@ -213,16 +128,20 @@ void MergedLayerDecorator::paintSunShading()
//Don't use city lights on non-earth planets!
if ( m_sunLocator->getCitylights() && m_sunLocator->planet()->id() == "earth" ) {
- QImage nighttile = loadDataset( m_cityLightsTextureLayer );
- if ( nighttile.isNull() )
+
+ TextureTile * tile = loadDataset( m_cityLightsTextureLayer );
+ if ( tile->state() == TextureTile::TileEmpty )
return;
+
+ QImage * nighttile = tile->tile();
+
for ( int cur_y = 0; cur_y < tileHeight; ++cur_y ) {
qreal lat = lat_scale * ( m_id.y() * tileHeight + cur_y ) - 0.5*M_PI;
qreal a = sin( ( lat+DEG2RAD * m_sunLocator->getLat() )/2.0 );
qreal c = cos(lat)*cos( -DEG2RAD * m_sunLocator->getLat() );
QRgb* scanline = (QRgb*)m_tile->scanLine( cur_y );
- QRgb* nscanline = (QRgb*)nighttile.scanLine( cur_y );
+ QRgb* nscanline = (QRgb*)nighttile->scanLine( cur_y );
qreal shade = 0;
qreal lastShade = -10.0;
diff --git a/marble/src/lib/MergedLayerDecorator.h b/marble/src/lib/MergedLayerDecorator.h
index 701407e..ee7564d 100644
--- a/marble/src/lib/MergedLayerDecorator.h
+++ b/marble/src/lib/MergedLayerDecorator.h
@@ -30,13 +30,15 @@ namespace Marble
class GeoSceneDocument;
class GeoSceneTexture;
class SunLocator;
+class TextureTile;
+class TileLoader;
class MergedLayerDecorator : public QObject
{
Q_OBJECT
public:
- explicit MergedLayerDecorator(SunLocator* sunLocator);
+ MergedLayerDecorator( TileLoader * const tileLoader, SunLocator* sunLocator );
virtual ~MergedLayerDecorator();
// The Parameter themeId is only used for displaying the TileId,
@@ -44,9 +46,6 @@ class MergedLayerDecorator : public QObject
void paint( const QString& themeId, GeoSceneDocument *mapTheme = 0 );
void paintTileId(const QString& themeId);
- void setShowClouds(bool show);
- bool showClouds() const;
-
void setShowTileId(bool show);
bool showTileId() const;
@@ -54,15 +53,12 @@ class MergedLayerDecorator : public QObject
void setInfo( TileId const &id );
Q_SIGNALS:
- void downloadTile(const QUrl& sourceUrl, const QString& destinationFileName,
- const QString& id, DownloadUsage );
void repaintMap();
private:
- QImage loadDataset( GeoSceneTexture *textureLayer );
+ TextureTile * loadDataset( GeoSceneTexture *textureLayer );
int maxDivisor( int maximum, int fullLength );
- void initClouds();
void initCityLights();
void paintSunShading();
@@ -70,15 +66,13 @@ class MergedLayerDecorator : public QObject
protected:
Q_DISABLE_COPY( MergedLayerDecorator )
+ TileLoader * const m_tileLoader;
QImage* m_tile;
TileId m_id;
SunLocator* m_sunLocator;
- bool m_cloudlayer;
bool m_showTileId;
GeoSceneDocument *m_cityLightsTheme;
- GeoSceneDocument *m_blueMarbleTheme;
GeoSceneTexture *m_cityLightsTextureLayer;
- GeoSceneTexture *m_cloudsTextureLayer;
};
}
diff --git a/marble/src/lib/SimpleTextureTile.cpp b/marble/src/lib/SimpleTextureTile.cpp
new file mode 100644
index 0000000..f60f190
--- /dev/null
+++ b/marble/src/lib/SimpleTextureTile.cpp
@@ -0,0 +1,57 @@
+// Copyright 2010 Jens-Michael Hoffmann <jmho at c-xx.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+#include "SimpleTextureTile.h"
+
+#include <limits>
+
+#include <QtCore/QString>
+#include <QtGui/QImage>
+
+namespace Marble
+{
+
+SimpleTextureTile::SimpleTextureTile( TileId const & tileId )
+ : m_id( tileId ),
+ m_state( StateEmpty ),
+ m_mergeRule( MergeCopy ),
+ m_expireSecs( std::numeric_limits<int>::max() ),
+ m_image( 0 )
+{
+}
+
+SimpleTextureTile::SimpleTextureTile( TileId const & tileId, QString const & fileName )
+ : m_id( tileId ),
+ m_state( StateExpired ),
+ m_mergeRule( MergeCopy ),
+ m_expireSecs( std::numeric_limits<int>::max() ),
+ m_image( new QImage( fileName ))
+{
+}
+
+SimpleTextureTile::~SimpleTextureTile()
+{
+ delete m_image;
+}
+
+void SimpleTextureTile::setImage( QByteArray const & data )
+{
+ if ( !m_image )
+ m_image = new QImage( QImage::fromData( data ));
+ else
+ m_image->loadFromData( data );
+}
+
+}
diff --git a/marble/src/lib/SimpleTextureTile.h b/marble/src/lib/SimpleTextureTile.h
new file mode 100644
index 0000000..5f824be
--- /dev/null
+++ b/marble/src/lib/SimpleTextureTile.h
@@ -0,0 +1,157 @@
+// Copyright 2010 Jens-Michael Hoffmann <jmho at c-xx.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MARBLE_SIMPLE_TEXTURE_TILE_H
+#define MARBLE_SIMPLE_TEXTURE_TILE_H
+
+#include <QtCore/QDateTime>
+
+#include "TileId.h"
+
+class QByteArray;
+class QImage;
+
+namespace Marble
+{
+class SimpleTileLoader;
+class TileLoader;
+
+class SimpleTextureTile
+{
+ friend class SimpleTileLoader;
+ friend class TileLoader;
+
+ public:
+ enum State {
+ StateEmpty,
+ StateScaled,
+ StateExpired,
+ StateUptodate
+ };
+
+ enum MergeRule {
+ MergeCopy,
+ MergeMultiply
+ };
+
+ explicit SimpleTextureTile( TileId const & );
+ SimpleTextureTile( TileId const & tileId, QString const & fileName );
+ ~SimpleTextureTile();
+
+ TileId const & id() const;
+ TileId const & composedTileId() const;
+ QDateTime const & lastModified() const;
+ bool expired() const;
+ QImage const * image() const;
+ QImage * image();
+ State state() const;
+ MergeRule mergeRule() const;
+
+ private:
+ Q_DISABLE_COPY( SimpleTextureTile )
+
+ void setState( State const );
+ void setImage( QByteArray const & data );
+ void setImage( QImage * const );
+ void setMergeRule( MergeRule const );
+ void setComposedTileId( TileId const & );
+ void setLastModified( QDateTime const & );
+ void setExpireSecs( int const );
+
+ TileId const m_id;
+ TileId m_composedTileId;
+ State m_state;
+ MergeRule m_mergeRule;
+ QDateTime m_lastModified;
+ int m_expireSecs;
+ QImage * m_image;
+};
+
+
+// inline definitions
+
+inline TileId const & SimpleTextureTile::id() const
+{
+ return m_id;
+}
+
+inline TileId const & SimpleTextureTile::composedTileId() const
+{
+ return m_composedTileId;
+}
+
+inline QDateTime const & SimpleTextureTile::lastModified() const
+{
+ return m_lastModified;
+}
+
+inline bool SimpleTextureTile::expired() const
+{
+ return m_lastModified.secsTo( QDateTime::currentDateTime() ) >= m_expireSecs;
+}
+
+inline QImage const * SimpleTextureTile::image() const
+{
+ return m_image;
+}
+
+inline QImage * SimpleTextureTile::image()
+{
+ return m_image;
+}
+
+inline SimpleTextureTile::State SimpleTextureTile::state() const
+{
+ return m_state;
+}
+
+inline SimpleTextureTile::MergeRule SimpleTextureTile::mergeRule() const
+{
+ return m_mergeRule;
+}
+
+inline void SimpleTextureTile::setState( State const state )
+{
+ m_state = state;
+}
+
+inline void SimpleTextureTile::setImage( QImage * const image )
+{
+ m_image = image;
+}
+
+inline void SimpleTextureTile::setMergeRule( MergeRule const mergeRule )
+{
+ m_mergeRule = mergeRule;
+}
+
+inline void SimpleTextureTile::setComposedTileId( TileId const & id )
+{
+ m_composedTileId = id;
+}
+
+inline void SimpleTextureTile::setLastModified( QDateTime const & lastModified )
+{
+ m_lastModified = lastModified;
+}
+
+inline void SimpleTextureTile::setExpireSecs( int const expireSecs )
+{
+ m_expireSecs = expireSecs;
+}
+
+}
+
+#endif
diff --git a/marble/src/lib/SimpleTileLoader.cpp b/marble/src/lib/SimpleTileLoader.cpp
new file mode 100644
index 0000000..16a4c3e
--- /dev/null
+++ b/marble/src/lib/SimpleTileLoader.cpp
@@ -0,0 +1,165 @@
+// Copyright 2010 Jens-Michael Hoffmann <jmho at c-xx.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+#include "SimpleTileLoader.h"
+
+#include <QtCore/QDateTime>
+#include <QtCore/QFileInfo>
+#include <QtGui/QImage>
+
+#include "GeoSceneTexture.h"
+#include "HttpDownloadManager.h"
+#include "MarbleDebug.h"
+#include "MarbleDirs.h"
+#include "SimpleTextureTile.h"
+#include "TileLoaderHelper.h"
+
+namespace Marble
+{
+
+SimpleTileLoader::SimpleTileLoader( MapThemeManager const * const mapThemeManager,
+ HttpDownloadManager * const downloadManager )
+{
+ connect( this, SIGNAL( downloadTile( QUrl, QString, QString, DownloadUsage )),
+ downloadManager, SLOT( addJob( QUrl, QString, QString, DownloadUsage )));
+ connect( downloadManager, SIGNAL( downloadComplete( QByteArray, QString )),
+ SLOT( updateTile( QByteArray, QString )));
+}
+
+// If the tile is locally available:
+// - if not expired: create SimpleTextureTile, set state to "uptodate", return it => done
+// - if expired: create SimpleTextureTile, state is set to Expired by default, trigger dl,
+
+SimpleTextureTile * SimpleTileLoader::loadTile( TileId const & composedTileId,
+ TileId const & baseTileId )
+{
+ QString const fileName = tileFileName( baseTileId );
+ QFileInfo const fileInfo( fileName );
+ if ( fileInfo.exists() ) {
+ // 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( baseTileId );
+ SimpleTextureTile * const tile = new SimpleTextureTile( baseTileId, fileName );
+ tile->setComposedTileId( composedTileId );
+ tile->setLastModified( fileInfo.lastModified() );
+ tile->setExpireSecs( textureLayer->expire() );
+
+ if ( !tile->expired() ) {
+ mDebug() << "SimpleTileLoader::loadTile" << baseTileId.toString() << "StateUptodate";
+ tile->setState( SimpleTextureTile::StateUptodate );
+ } else {
+ mDebug() << "SimpleTileLoader::loadTile" << baseTileId.toString() << "StateExpired";
+ m_waitingForUpdate.insert( baseTileId, tile );
+ triggerDownload( baseTileId );
+ }
+ return tile;
+ }
+
+ // tile was not locally available => trigger download and look for tiles in other levels
+ // for scaling
+ SimpleTextureTile * const tile = new SimpleTextureTile( baseTileId );
+ tile->setComposedTileId( composedTileId );
+ m_waitingForUpdate.insert( baseTileId, tile );
+ triggerDownload( baseTileId );
+ QImage * const replacementTile = scaledLowerLevelTile( baseTileId );
+ if ( replacementTile ) {
+ mDebug() << "SimpleTileLoader::loadTile" << baseTileId.toString() << "StateScaled";
+ tile->setImage( replacementTile );
+ tile->setState( SimpleTextureTile::StateScaled );
+ } else {
+ mDebug() << "SimpleTileLoader::loadTile" << baseTileId.toString() << "No tiles found";
+ }
+ return tile;
+}
+
+void SimpleTileLoader::updateTile( QByteArray const & data, QString const & tileId )
+{
+ TileId const id = TileId::fromString( tileId );
+ SimpleTextureTile * const tile = m_waitingForUpdate.value( id, 0 );
+ Q_ASSERT( tile );
+ m_waitingForUpdate.remove( id );
+ tile->setImage( data );
+ tile->setState( SimpleTextureTile::StateUptodate );
+ tile->setLastModified( QDateTime::currentDateTime() );
+ emit tileCompleted( tile->composedTileId(), id );
+}
+
+inline GeoSceneTexture const * SimpleTileLoader::findTextureLayer( TileId const & id ) const
+{
+ GeoSceneTexture const * const textureLayer = m_textureLayers.value( id.mapThemeIdHash(), 0 );
+ Q_ASSERT( textureLayer );
+ return textureLayer;
+}
+
+inline GeoSceneTexture * SimpleTileLoader::findTextureLayer( TileId const & id )
+{
+ GeoSceneTexture * const textureLayer = m_textureLayers.value( id.mapThemeIdHash(), 0 );
+ Q_ASSERT( textureLayer );
+ return textureLayer;
+}
+
+QString SimpleTileLoader::tileFileName( TileId const & tileId ) const
+{
+ GeoSceneTexture const * const textureLayer = findTextureLayer( tileId );
+ return MarbleDirs::path( TileLoaderHelper::relativeTileFileName
+ ( textureLayer, tileId.zoomLevel(), tileId.x(), tileId.y() ));
+}
+
+void SimpleTileLoader::triggerDownload( TileId const & id )
+{
+ GeoSceneTexture * const textureLayer = findTextureLayer( id );
+ QUrl const sourceUrl = TileLoaderHelper::downloadUrl( textureLayer, id.zoomLevel(), id.x(),
+ id.y() );
+ QString const destFileName = TileLoaderHelper::relativeTileFileName( textureLayer, id.zoomLevel(),
+ id.x(), id.y() );
+ emit downloadTile( sourceUrl, destFileName, id.toString(), DownloadBrowse );
+}
+
+ // TODO: get lastModified time stamp into the SimpleTextureTile
+QImage * SimpleTileLoader::scaledLowerLevelTile( TileId const & id )
+{
+ mDebug() << "SimpleTileLoader::scaledLowerLevelTile" << id.toString();
+ QImage * result = 0;
+ int level = id.zoomLevel() - 1;
+ while ( !result && level >= 0 ) {
+ int const deltaLevel = id.zoomLevel() - level;
+ TileId const replacementTileId( id.mapThemeIdHash(), level,
+ id.x() >> deltaLevel, id.y() >> deltaLevel );
+ mDebug() << "SimpleTileLoader::scaledLowerLevelTile" << "trying" << replacementTileId.toString();
+ QString const fileName = tileFileName( replacementTileId );
+ QFileInfo const fileInfo( fileName );
+ if ( fileInfo.exists() ) {
+ QImage const toScale( fileName );
+ // which rect to scale?
+ QSize const size = toScale.size();
+ int const restTileX = id.x() % ( 1 << deltaLevel );
+ int const restTileY = id.y() % ( 1 << deltaLevel );
+ int const partWidth = toScale.width() >> deltaLevel;
+ int const partHeight = toScale.height() >> deltaLevel;
+ int const startX = restTileX * partWidth;
+ int const startY = restTileY * partHeight;
+ 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() ));
+ }
+ --level;
+ }
+ return result;
+}
+
+}
+
+#include "SimpleTileLoader.moc"
diff --git a/marble/src/lib/SimpleTileLoader.h b/marble/src/lib/SimpleTileLoader.h
new file mode 100644
index 0000000..9ab3ad1
--- /dev/null
+++ b/marble/src/lib/SimpleTileLoader.h
@@ -0,0 +1,80 @@
+// Copyright 2010 Jens-Michael Hoffmann <jmho at c-xx.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MARBLE_SIMPLE_TILE_LOADER_H
+#define MARBLE_SIMPLE_TILE_LOADER_H
+
+#include <QtCore/QHash>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+#include "TileId.h"
+#include "global.h"
+
+class QByteArray;
+class QImage;
+class QUrl;
+
+namespace Marble
+{
+class HttpDownloadManager; // remove?
+class GeoSceneTexture;
+class MapThemeManager;
+class SimpleTextureTile;
+
+class SimpleTileLoader: public QObject
+{
+ Q_OBJECT
+
+ public:
+ SimpleTileLoader( MapThemeManager const * const, HttpDownloadManager * const );
+
+ SimpleTextureTile * loadTile( TileId const & composedTileId, TileId const & baseTileId );
+ void setTextureLayers( QHash<uint, GeoSceneTexture*> const & );
+
+ public Q_SLOTS:
+ void updateTile( QByteArray const & imageData, QString const & tileId );
+
+ Q_SIGNALS:
+ void downloadTile( QUrl const & sourceUrl, QString const & destinationFileName,
+ QString const & id, DownloadUsage );
+
+ // when this signal is emitted, the SimpleTileLoader gives up ownership of
+ // the corrsponding tile. Might be better to explicitely transfer...
+ void tileCompleted( TileId const & composedTileId, TileId const & baseTileId );
+
+ private:
+ GeoSceneTexture const * findTextureLayer( TileId const & ) const;
+ GeoSceneTexture * findTextureLayer( TileId const & );
+ QString tileFileName( TileId const & ) const;
+ void triggerDownload( TileId const & );
+ QImage * scaledLowerLevelTile( TileId const & );
+
+ // TODO: comment about uint hash key
+ QHash<uint, GeoSceneTexture*> m_textureLayers;
+
+ // contains tiles, for which a download has been triggered
+ // because the tile was not there at all or is expired.
+ QHash<TileId, SimpleTextureTile*> m_waitingForUpdate;
+};
+
+inline void SimpleTileLoader::setTextureLayers( QHash<uint, GeoSceneTexture*> const & layers )
+{
+ m_textureLayers = layers;
+}
+
+}
+
+#endif
diff --git a/marble/src/lib/SphericalScanlineTextureMapper.cpp b/marble/src/lib/SphericalScanlineTextureMapper.cpp
index 9ce169f..70390ab 100644
--- a/marble/src/lib/SphericalScanlineTextureMapper.cpp
+++ b/marble/src/lib/SphericalScanlineTextureMapper.cpp
@@ -28,9 +28,10 @@
using namespace Marble;
-SphericalScanlineTextureMapper::SphericalScanlineTextureMapper( TileLoader *tileLoader,
- QObject * parent )
- : AbstractScanlineTextureMapper( tileLoader, parent )
+SphericalScanlineTextureMapper::SphericalScanlineTextureMapper( GeoSceneTexture *textureLayer,
+ TileLoader *tileLoader,
+ QObject *parent )
+ : AbstractScanlineTextureMapper( textureLayer, tileLoader, parent )
{
m_interlaced = false;
}
diff --git a/marble/src/lib/SphericalScanlineTextureMapper.h b/marble/src/lib/SphericalScanlineTextureMapper.h
index 6bfe7a5..5c00b41 100644
--- a/marble/src/lib/SphericalScanlineTextureMapper.h
+++ b/marble/src/lib/SphericalScanlineTextureMapper.h
@@ -36,7 +36,8 @@ class TileLoader;
class SphericalScanlineTextureMapper : public AbstractScanlineTextureMapper
{
public:
- explicit SphericalScanlineTextureMapper( TileLoader *tileLoader, QObject * parent =0 );
+ SphericalScanlineTextureMapper( GeoSceneTexture *textureLayer, TileLoader *tileLoader,
+ QObject *parent = 0 );
void mapTexture( ViewParams *viewParams );
diff --git a/marble/src/lib/TextureTile.cpp b/marble/src/lib/TextureTile.cpp
index 572f58c..515828e 100644
--- a/marble/src/lib/TextureTile.cpp
+++ b/marble/src/lib/TextureTile.cpp
@@ -18,6 +18,7 @@
#include <cmath>
+#include "SimpleTextureTile.h"
#include "global.h"
#include "MarbleDebug.h"
#include "GeoSceneTexture.h"
@@ -63,9 +64,10 @@ TextureTilePrivate::TextureTilePrivate( const TileId& id ) :
AbstractTilePrivate( id ),
jumpTable8(0),
jumpTable32(0),
- m_rawtile(),
+ m_resultTile(),
m_depth(0),
- m_isGrayscale(false)
+ m_isGrayscale( false ),
+ m_forMergedLayerDecorator( false )
{
}
@@ -73,6 +75,14 @@ TextureTilePrivate::~TextureTilePrivate()
{
delete [] jumpTable32;
delete [] jumpTable8;
+
+ QVector<SimpleTextureTile*>::const_iterator pos = m_baseTiles.constBegin();
+ QVector<SimpleTextureTile*>::const_iterator const end = m_baseTiles.constEnd();
+ for (; pos != end; ++pos )
+ // only delete tiles with stateUptodate as the other ones are managed
+ // by the SimpleTileLoader until they are fully up to date.
+ if ( (*pos)->state() == SimpleTextureTile::StateUptodate )
+ delete *pos;
}
uint TextureTilePrivate::pixel( int x, int y ) const
@@ -81,15 +91,15 @@ uint TextureTilePrivate::pixel( int x, int y ) const
if ( m_isGrayscale )
return (jumpTable8)[y][x];
else
- return m_rawtile.color( (jumpTable8)[y][x] );
+ return m_resultTile.color( (jumpTable8)[y][x] );
}
if ( m_depth == 32 )
return (jumpTable32)[y][x];
if ( m_depth == 1 && !m_isGrayscale )
- return m_rawtile.color((jumpTable8)[y][x/8] >> 7);
+ return m_resultTile.color((jumpTable8)[y][x/8] >> 7);
- return m_rawtile.pixel( x, y );
+ return m_resultTile.pixel( x, y );
}
uint TextureTilePrivate::pixelF( qreal x, qreal y, const QRgb& topLeftValue ) const
@@ -102,7 +112,7 @@ uint TextureTilePrivate::pixelF( qreal x, qreal y, const QRgb& topLeftValue ) co
qreal fY = y - iY;
// Interpolation in y-direction
- if ( ( iY + 1 ) < m_rawtile.height() ) {
+ if ( ( iY + 1 ) < m_resultTile.height() ) {
QRgb bottomLeftValue = pixel( iX, iY + 1 );
// #define CHEAPHIGH
@@ -122,7 +132,7 @@ uint TextureTilePrivate::pixelF( qreal x, qreal y, const QRgb& topLeftValue ) co
qreal ml_blue = ( 1.0 - fY ) * qBlue ( topLeftValue ) + fY * qBlue ( bottomLeftValue );
#endif
// Interpolation in x-direction
- if ( iX + 1 < m_rawtile.width() ) {
+ if ( iX + 1 < m_resultTile.width() ) {
qreal fX = x - iX;
@@ -174,7 +184,7 @@ uint TextureTilePrivate::pixelF( qreal x, qreal y, const QRgb& topLeftValue ) co
}
else {
// Interpolation in x-direction
- if ( iX + 1 < m_rawtile.width() ) {
+ if ( iX + 1 < m_resultTile.width() ) {
qreal fX = x - iX;
@@ -207,49 +217,34 @@ uint TextureTilePrivate::pixelF( qreal x, qreal y, const QRgb& topLeftValue ) co
return topLeftValue;
}
-void TextureTilePrivate::scaleTileFrom( GeoSceneTexture *textureLayer, QImage &tile,
- qreal sourceX, qreal sourceY, int sourceLevel,
- int targetX, int targetY, int targetLevel )
+inline void TextureTilePrivate::mergeCopyToResult( SimpleTextureTile const * const other )
{
- const int levelZeroColumns = textureLayer->levelZeroColumns();
- const int levelZeroRows = textureLayer->levelZeroRows();
- const int rowsRequestedLevel = TileLoaderHelper::levelToRow( levelZeroRows, targetLevel );
- const int columnsRequestedLevel = TileLoaderHelper::levelToColumn( levelZeroColumns,
- targetLevel );
- const int rowsCurrentLevel = TileLoaderHelper::levelToRow( levelZeroRows, sourceLevel );
- const int columnsCurrentLevel = TileLoaderHelper::levelToColumn( levelZeroColumns,
- sourceLevel );
-
- // mDebug() << "About to start cropping an existing image.";
-
- QSize tilesize = tile.size();
- qreal normalizedX2 = (qreal)(targetX + 1) / (qreal)( rowsRequestedLevel );
- qreal normalizedY2 = (qreal)(targetY + 1) / (qreal)( columnsRequestedLevel );
- qreal currentX2 = normalizedX2 * (qreal)( rowsCurrentLevel );
- qreal currentY2 = normalizedY2 * (qreal)( columnsCurrentLevel );
-
- // Determine the rectangular section of the previous tile data
- // which we intend to copy from:
- int left = (int)( ( sourceX - (int)( sourceX ) ) * tile.width() );
- int top = (int)( ( sourceY - (int)( sourceY ) ) * tile.height() );
- int right = (int)( ( currentX2 - (int)( sourceX ) ) * tile.width() ) - 1;
- int bottom = (int)( ( currentY2 - (int)( sourceY ) ) * tile.height() ) - 1;
-
- // Important: Scaling a null image during the next step would be fatal
- // So we make sure the width and height is at least 1.
- int rectWidth = ( right - left > 1 ) ? right - left : 1;
- int rectHeight = ( bottom - top > 1 ) ? bottom - top : 1;
-
- // This should not create any memory leaks as
- // 'copy' and 'scaled' return a value (on the
- // stack) which gets deep copied always into the
- // same place for m_rawtile on the heap:
- tile = tile.copy( left, top, rectWidth, rectHeight );
- tile = tile.scaled( tilesize ); // TODO: use correct size
- m_state = AbstractTile::TilePartial;
- // mDebug() << "Finished scaling up the Temporary Tile.";
+ m_resultTile = other->image()->copy();
}
+void TextureTilePrivate::mergeMultiplyToResult( SimpleTextureTile const * const other )
+{
+ // for this operation we assume that the tiles have the same size
+ QImage const * const otherImage = other->image();
+ Q_ASSERT( m_resultTile.size() == otherImage->size() );
+ if ( m_resultTile.size() != otherImage->size() )
+ return;
+
+ int const width = m_resultTile.width();
+ int const height = m_resultTile.height();
+ for ( int y = 0; y < height; ++y ) {
+ for ( int x = 0; x < width; ++x ) {
+ qreal const c = qRed( otherImage->pixel( x, y )) / 255.0;
+ QRgb const oldPixel = m_resultTile.pixel( x, y );
+ int const oldRed = qRed( oldPixel );
+ int const oldGreen = qGreen( oldPixel );
+ int const oldBlue = qBlue( oldPixel );
+ m_resultTile.setPixel( x, y, qRgb(( int )( oldRed + ( 255 - oldRed ) * c ),
+ ( int )( oldGreen + ( 255 - oldGreen ) * c ),
+ ( int )( oldBlue + ( 255 - oldBlue ) * c )));
+ }
+ }
+}
TextureTile::TextureTile( TileId const& id, QObject * parent )
: AbstractTile( *new TextureTilePrivate( id ), parent ), d(0)
@@ -271,173 +266,73 @@ TextureTile::~TextureTile()
{
}
-void TextureTile::setImage( const QByteArray & data )
+bool TextureTile::expired() const
{
- d->m_rawtile = QImage::fromData( data );
- d->m_depth = d->m_rawtile.depth();
- d->m_isGrayscale = d->m_rawtile.isGrayscale();
- d->m_created = QDateTime::currentDateTime();
- initJumpTables();
- d->m_state = TileComplete;
+ bool result = false;
+ QVector<SimpleTextureTile*>::const_iterator pos = d->m_baseTiles.constBegin();
+ QVector<SimpleTextureTile*>::const_iterator const end = d->m_baseTiles.constEnd();
+ for (; pos != end; ++pos )
+ result |= (*pos)->expired();
+ return result;
}
-void TextureTile::loadDataset( GeoSceneTexture *textureLayer,
- QCache<TileId, TextureTile> *tileCache )
+bool TextureTile::forMergedLayerDecorator() const
{
- // mDebug() << "TextureTile::loadDataset" << level << x << y;
- QImage temptile;
-
- d->m_used = true; // Needed to avoid frequent deletion of tiles
-
- QString absfilename;
-
- // If the tile level offers the requested tile then load it.
- // Otherwise cycle from the requested tilelevel down to one where
- // the requested area is covered. Then scale the area to create a
- // replacement for the tile that has been requested.
-
- const int levelZeroColumns = textureLayer->levelZeroColumns();
- const int levelZeroRows = textureLayer->levelZeroRows();
- const int rowsRequestedLevel = TileLoaderHelper::levelToRow( levelZeroRows,
- d->m_id.zoomLevel() );
- const int columnsRequestedLevel = TileLoaderHelper::levelToColumn( levelZeroColumns,
- d->m_id.zoomLevel() );
- bool tileFound = false;
- for ( int currentLevel = d->m_id.zoomLevel(); !tileFound && currentLevel > -1; --currentLevel ) {
-
- const int rowsCurrentLevel =
- TileLoaderHelper::levelToRow( levelZeroRows, currentLevel );
- const int columnsCurrentLevel =
- TileLoaderHelper::levelToColumn( levelZeroColumns, currentLevel );
-
- qreal normalizedX = (qreal)( d->m_id.x() ) / (qreal)( rowsRequestedLevel );
- qreal normalizedY = (qreal)( d->m_id.y() ) / (qreal)( columnsRequestedLevel );
- qreal currentX = normalizedX * (qreal)( rowsCurrentLevel );
- qreal currentY = normalizedY * (qreal)( columnsCurrentLevel );
-
- const QDateTime now = QDateTime::currentDateTime();
- QDateTime lastModified;
-
- bool download = false;
- bool currentTileAvailable = false;
-
- // Check whether the current tile id is available in the CACHE:
- const TileId currentTileId( currentLevel, (int)(currentX), (int)(currentY) );
- if ( tileCache ) {
- TextureTile *currentTile = tileCache->take( currentTileId );
- if ( currentTile ) {
- // the tile was in the cache, but is it up to date?
- lastModified = currentTile->created();
- if ( lastModified.secsTo( now ) < textureLayer->expire()) {
- temptile = currentTile->rawtile();
- currentTileAvailable = true;
- }
- delete currentTile;
- }
- }
- // If the current tile id is not in the cache or if it was
- // in the cache but has expired load from DISK:
-
- if ( temptile.isNull() ) {
- QString relfilename =
- TileLoaderHelper::relativeTileFileName( textureLayer, currentLevel,
- (int)(currentX), (int)(currentY) );
- absfilename = MarbleDirs::path( relfilename );
- const QFileInfo fileInfo( absfilename );
- lastModified = fileInfo.lastModified();
-
- // - if the file does not exist, we want to download it and search an
- // existing tile of a lower zoom level for immediate display
- // - if the file exists and is expired according to the value of the
- // expire element we want to download it again and display the old
- // tile until the new one is there. Once the updated tile is
- // available, it should get displayed.
-
- if ( !fileInfo.exists() ) {
-// mDebug() << "File does not exist:" << fileInfo.filePath();
- download = true;
- }
- else if ( lastModified.secsTo( now ) > textureLayer->expire() ) {
-// mDebug() << "File does exist, but is expired:" << fileInfo.filePath()
-// << "age (seconds):" << lastModified.secsTo( now )
-// << "allowed age:" << textureLayer->expire();
- download = true;
- }
-
- if ( fileInfo.exists() ) {
-
- temptile.load( absfilename );
- // mDebug() << "TextureTile::loadDataset "
- // << "depth:" << temptile.depth()
- // << "format:" << temptile.format()
- // << "bytesPerLine:" << temptile.bytesPerLine()
- // << "numBytes:" << temptile.numBytes() ;
- download |= temptile.isNull();
- currentTileAvailable = true;
- }
- }
+ return d->m_forMergedLayerDecorator;
+}
- if ( currentTileAvailable ) {
- if ( !temptile.isNull() ) {
-
- // Don't scale if the current tile isn't a fallback
- if ( d->m_id.zoomLevel() != currentLevel ) {
- d->scaleTileFrom( textureLayer, temptile, currentX, currentY, currentLevel,
- d->m_id.x(), d->m_id.y(), d->m_id.zoomLevel() );
- }
- else {
- d->m_state = TileComplete;
- }
-
- d->m_rawtile = temptile;
- d->m_depth = d->m_rawtile.depth();
- d->m_created = lastModified;
- tileFound = true;
- initJumpTables();
- }
- }
+void TextureTile::setForMergedLayerDecorator()
+{
+ d->m_forMergedLayerDecorator = true;
+}
- if ( download ) {
- QUrl sourceUrl =
- TileLoaderHelper::downloadUrl( textureLayer, currentLevel,
- currentX, currentY );
- QString destFileName =
- TileLoaderHelper::relativeTileFileName( textureLayer, currentLevel,
- currentX, currentY );
-// mDebug() << "emit downloadTile(" << sourceUrl << destFileName << ");";
- emit downloadTile( sourceUrl, destFileName, currentTileId.toString(), DownloadBrowse );
- }
- }
+void TextureTile::addBaseTile( SimpleTextureTile * const simpleTile )
+{
+ d->m_baseTiles.append( simpleTile );
+ deriveCompletionState();
+}
-// mDebug() << "TextureTile::loadDataset end";
+void TextureTile::deriveCompletionState()
+{
+ QMap<SimpleTextureTile::State, int> count;
+ QVector<SimpleTextureTile*>::const_iterator pos = d->m_baseTiles.constBegin();
+ QVector<SimpleTextureTile*>::const_iterator const end = d->m_baseTiles.constEnd();
+ for (; pos != end; ++pos )
+ ++count[ (*pos)->state() ];
+
+ if ( count[ SimpleTextureTile::StateUptodate ] == d->m_baseTiles.size() )
+ d->m_state = TileComplete;
+ else if ( count[ SimpleTextureTile::StateEmpty ] == d->m_baseTiles.size() )
+ d->m_state = TileEmpty;
+ else
+ d->m_state = TilePartial;
}
void TextureTile::initJumpTables()
{
// mDebug() << "Entered initJumpTables( bool ) of Tile" << d->m_id;
- if ( d->m_rawtile.isNull() ) {
+ if ( d->m_resultTile.isNull() ) {
qWarning() << "An essential tile is missing. Please rerun the application.";
return;
}
- switch ( d->m_depth ) {
+ switch ( d->m_resultTile.depth() ) {
case 48:
case 32:
delete [] d->jumpTable32;
- d->jumpTable32 = jumpTableFromQImage32( d->m_rawtile );
+ d->jumpTable32 = jumpTableFromQImage32( d->m_resultTile );
break;
case 8:
case 1:
delete [] d->jumpTable8;
- d->jumpTable8 = jumpTableFromQImage8( d->m_rawtile );
+ d->jumpTable8 = jumpTableFromQImage8( d->m_resultTile );
break;
default:
- qWarning() << "Color depth" << d->m_depth << " is not supported.";
+ qWarning() << "Color depth" << d->m_resultTile.depth() << " is not supported.";
return;
}
- d->m_isGrayscale = d->m_rawtile.isGrayscale();
}
uint TextureTile::pixel( int x, int y ) const
@@ -467,17 +362,45 @@ int TextureTile::depth() const
int TextureTile::numBytes() const
{
- return d->m_rawtile.numBytes();
+ return d->m_resultTile.numBytes();
}
QImage TextureTile::rawtile()
{
- return d->m_rawtile;
+ return d->m_resultTile;
}
QImage * TextureTile::tile()
{
- return &(d->m_rawtile);
+ return &(d->m_resultTile);
+}
+
+bool TextureTile::hasBaseTiles() const
+{
+ return !d->m_baseTiles.isEmpty();
+}
+
+void TextureTile::initResultTile()
+{
+ Q_ASSERT( hasBaseTiles() );
+ QVector<SimpleTextureTile*>::const_iterator pos = d->m_baseTiles.constBegin();
+ QVector<SimpleTextureTile*>::const_iterator const end = d->m_baseTiles.constEnd();
+ for (; pos != end; ++pos )
+ if ( (*pos)->state() != SimpleTextureTile::StateEmpty )
+ switch ( (*pos)->mergeRule() ) {
+ case SimpleTextureTile::MergeCopy:
+ d->mergeCopyToResult( *pos );
+ break;
+ case SimpleTextureTile::MergeMultiply:
+ d->mergeMultiplyToResult( *pos );
+ break;
+ }
+
+ initJumpTables();
+
+ // for now, this seems to be the best place for initializing this stuff
+ d->m_depth = d->m_resultTile.depth();
+ d->m_isGrayscale = d->m_resultTile.isGrayscale();
}
#include "TextureTile.moc"
diff --git a/marble/src/lib/TextureTile.h b/marble/src/lib/TextureTile.h
index 7a0b694..2d98306 100644
--- a/marble/src/lib/TextureTile.h
+++ b/marble/src/lib/TextureTile.h
@@ -35,24 +35,24 @@ namespace Marble
class TextureTilePrivate;
class GeoSceneTexture;
+class SimpleTextureTile;
+class TileLoader;
class TextureTile : public AbstractTile
{
Q_OBJECT
+ friend class TileLoader;
public:
explicit TextureTile( TileId const& tid, QObject * parent = 0 );
virtual ~TextureTile();
- void setImage( const QByteArray & data );
-
- // TODO: Move into DatasetProvider:
- void loadDataset( GeoSceneTexture *textureLayer,
- QCache<TileId, TextureTile> *tileCache = 0 );
-
int depth() const;
-
int numBytes() const;
+ bool expired() const;
+
+ bool forMergedLayerDecorator() const;
+ void setForMergedLayerDecorator();
QImage rawtile();
QImage *tile();
@@ -81,7 +81,13 @@ class TextureTile : public AbstractTile
private:
Q_DECLARE_PRIVATE( TextureTile )
Q_DISABLE_COPY( TextureTile )
+
+ void addBaseTile( SimpleTextureTile * const );
+ void deriveCompletionState();
void initJumpTables();
+ bool hasBaseTiles() const;
+ void initResultTile();
+
TextureTilePrivate *d;
};
diff --git a/marble/src/lib/TextureTile_p.h b/marble/src/lib/TextureTile_p.h
index cd7cfd5..638b747 100644
--- a/marble/src/lib/TextureTile_p.h
+++ b/marble/src/lib/TextureTile_p.h
@@ -20,11 +20,12 @@
#include "AbstractTile_p.h"
+#include <QtCore/QVector>
#include <QtGui/QImage>
namespace Marble
{
-
+class SimpleTextureTile;
class TextureTilePrivate : AbstractTilePrivate
{
@@ -34,20 +35,20 @@ class TextureTilePrivate : AbstractTilePrivate
uchar **jumpTable8;
uint **jumpTable32;
- QImage m_rawtile;
+ QVector<SimpleTextureTile*> m_baseTiles;
+ QImage m_resultTile;
int m_depth;
bool m_isGrayscale;
+ bool m_forMergedLayerDecorator;
explicit TextureTilePrivate( const TileId& id );
virtual ~TextureTilePrivate();
inline uint pixel( int x, int y ) const;
inline uint pixelF( qreal x, qreal y, const QRgb& pixel ) const;
-
- void scaleTileFrom( GeoSceneTexture *textureLayer, QImage &tile,
- qreal sourceX, qreal sourceY, int sourceLevel,
- int targetX, int targetY, int targetLevel );
+ void mergeCopyToResult( SimpleTextureTile const * const baseTile );
+ void mergeMultiplyToResult( SimpleTextureTile const * const baseTile );
};
}
diff --git a/marble/src/lib/TileId.cpp b/marble/src/lib/TileId.cpp
index efeca2f..2209704 100644
--- a/marble/src/lib/TileId.cpp
+++ b/marble/src/lib/TileId.cpp
@@ -5,34 +5,42 @@
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
-// Copyright 2008 Jens-Michael Hoffmann <jensmh at gmx.de>
+// Copyright 2008, 2010 Jens-Michael Hoffmann <jensmh at gmx.de>
//
// Own
#include "TileId.h"
+#include <QtCore/QStringList>
+
namespace Marble
{
-TileId::TileId( int zoomLevel, int tileX, int tileY )
- : m_zoomLevel( zoomLevel ), m_tileX( tileX ), m_tileY( tileY )
+TileId::TileId( QString const & mapThemeId, int zoomLevel, int tileX, int tileY )
+ : m_mapThemeIdHash( qHash( mapThemeId )), m_zoomLevel( zoomLevel ), m_tileX( tileX ), m_tileY( tileY )
+{
+}
+
+TileId::TileId( uint mapThemeIdHash, int zoomLevel, int tileX, int tileY )
+ : m_mapThemeIdHash( mapThemeIdHash ), m_zoomLevel( zoomLevel ), m_tileX( tileX ), m_tileY( tileY )
{
}
TileId::TileId()
- : m_zoomLevel( 0 ), m_tileX( 0 ), m_tileY( 0 )
+ : m_mapThemeIdHash( 0 ), m_zoomLevel( 0 ), m_tileX( 0 ), m_tileY( 0 )
{
}
TileId TileId::fromString( QString const& idStr )
{
- int first = idStr.indexOf( ':' );
- int last = idStr.lastIndexOf( ':' );
-
- return TileId( idStr.left( first ).toInt(),
- idStr.mid( first + 1, last - first - 1 ).toInt(),
- idStr.mid( last + 1 ).toInt() );
+ QStringList const components = idStr.split( ':', QString::SkipEmptyParts );
+ Q_ASSERT( components.size() == 4 );
+
+ uint const mapThemeIdHash = components[ 0 ].toUInt();
+ int const zoomLevel = components[ 1 ].toInt();
+ int const tileX = components[ 2 ].toInt();
+ int const tileY = components[ 3 ].toInt();
+ return TileId( mapThemeIdHash, zoomLevel, tileX, tileY );
}
-
}
diff --git a/marble/src/lib/TileId.h b/marble/src/lib/TileId.h
index ffab41b..43b97b1 100644
--- a/marble/src/lib/TileId.h
+++ b/marble/src/lib/TileId.h
@@ -5,7 +5,7 @@
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
-// Copyright 2008 Jens-Michael Hoffmann <jensmh at gmx.de>
+// Copyright 2008, 2010 Jens-Michael Hoffmann <jensmh at gmx.de>
//
#ifndef MARBLE_TILE_ID_H
@@ -23,17 +23,20 @@ class TileId
friend uint qHash( TileId const& );
public:
- TileId( int zoomLevel, int tileX, int tileY );
+ TileId( QString const & mapThemeId, int zoomLevel, int tileX, int tileY );
+ TileId( uint mapThemeIdHash, int zoomLevel, int tileX, int tileY );
TileId();
int zoomLevel() const;
int x() const;
int y() const;
+ uint mapThemeIdHash() const;
QString toString() const;
static TileId fromString( QString const& );
private:
+ uint m_mapThemeIdHash;
int m_zoomLevel;
int m_tileX;
int m_tileY;
@@ -60,16 +63,22 @@ inline int TileId::y() const
return m_tileY;
}
+inline uint TileId::mapThemeIdHash() const
+{
+ return m_mapThemeIdHash;
+}
+
inline QString TileId::toString() const
{
- return QString( "%1:%2:%3" ).arg( m_zoomLevel ).arg( m_tileX ).arg( m_tileY );
+ return QString( "%1:%2:%3:%4" ).arg( m_mapThemeIdHash ).arg( m_zoomLevel ).arg( m_tileX ).arg( m_tileY );
}
inline bool operator==( TileId const& lhs, TileId const& rhs )
{
return lhs.m_zoomLevel == rhs.m_zoomLevel
&& lhs.m_tileX == rhs.m_tileX
- && lhs.m_tileY == rhs.m_tileY;
+ && lhs.m_tileY == rhs.m_tileY
+ && lhs.m_mapThemeIdHash == rhs.m_mapThemeIdHash;
}
inline uint qHash( TileId const& tid )
@@ -77,7 +86,7 @@ inline uint qHash( TileId const& tid )
const quint64 tmp = (( quint64 )( tid.m_zoomLevel ) << 36 )
+ (( quint64 )( tid.m_tileX ) << 18 )
+ ( quint64 )( tid.m_tileY );
- return ::qHash( tmp );
+ return ::qHash( tmp ) ^ tid.m_mapThemeIdHash;
}
}
diff --git a/marble/src/lib/TileLoader.cpp b/marble/src/lib/TileLoader.cpp
index f488169..7b3126c 100644
--- a/marble/src/lib/TileLoader.cpp
+++ b/marble/src/lib/TileLoader.cpp
@@ -3,7 +3,7 @@
*
* Copyright 2005-2007 Torsten Rahn <tackat at kde.org>
* Copyright 2007 Inge Wallin <ingwa at kde.org>
- * Copyright 2008,2009 Jens-Michael Hoffmann <jensmh at gmx.de>
+ * Copyright 2008, 2009, 2010 Jens-Michael Hoffmann <jensmh at gmx.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,17 +21,22 @@
* Boston, MA 02110-1301, USA.
*/
-
#include "TileLoader.h"
+#include "SimpleTextureTile.h"
+#include "SimpleTileLoader.h"
+#include "MarbleModel.h"
#include "global.h"
+#include "GeoSceneDocument.h"
+#include "GeoSceneHead.h"
#include "GeoSceneLayer.h"
+#include "GeoSceneMap.h"
#include "GeoSceneTexture.h"
#include "HttpDownloadManager.h"
#include "DatasetProvider.h"
#include "TextureTile.h"
+#include "MapThemeManager.h"
#include "MarbleDirs.h"
-#include "MarbleModel.h"
#include "TileLoaderHelper.h"
#include "MarbleDebug.h"
@@ -55,29 +60,34 @@ class TileLoaderPrivate
public:
TileLoaderPrivate()
: m_datasetProvider( 0 ),
- m_downloadManager( 0 ),
- m_layer( 0 ),
- m_tileWidth( 0 ),
- m_tileHeight( 0 )
+ m_mapThemeManager( 0 ),
+ m_simpleTileLoader( 0 )
{
m_tileCache.setMaxCost( 20000 * 1024 ); // Cache size measured in bytes
}
DatasetProvider *m_datasetProvider;
- HttpDownloadManager *m_downloadManager;
- GeoSceneLayer *m_layer;
+ MapThemeManager const *m_mapThemeManager;
+ // TODO: comment about uint hash key
+ QHash<uint, GeoSceneLayer const *> m_sceneLayers;
+ QHash<uint, GeoSceneTexture*> m_textureLayers;
+ SimpleTileLoader *m_simpleTileLoader;
QHash <TileId, TextureTile*> m_tilesOnDisplay;
- int m_tileWidth;
- int m_tileHeight;
QCache <TileId, TextureTile> m_tileCache;
};
-
-TileLoader::TileLoader( HttpDownloadManager *downloadManager, MarbleModel* parent )
- : d( new TileLoaderPrivate() ),
- m_parent( parent )
+TileLoader::TileLoader( MapThemeManager const * const mapThemeManager,
+ HttpDownloadManager * const downloadManager, MarbleModel * const model )
+ : d( new TileLoaderPrivate ),
+ m_parent( model )
{
+ d->m_mapThemeManager = mapThemeManager;
+ initTextureLayers();
+ d->m_simpleTileLoader = new SimpleTileLoader( mapThemeManager, downloadManager );
+ d->m_simpleTileLoader->setTextureLayers( d->m_textureLayers );
+ connect( d->m_simpleTileLoader, SIGNAL( tileCompleted( TileId, TileId )),
+ SLOT( updateTile( TileId, TileId )));
setDownloadManager( downloadManager );
}
@@ -85,49 +95,12 @@ TileLoader::~TileLoader()
{
flush();
d->m_tileCache.clear();
- if ( d->m_downloadManager != 0 )
- d->m_downloadManager->disconnect( this );
-
+ delete d->m_simpleTileLoader;
delete d;
}
void TileLoader::setDownloadManager( HttpDownloadManager *downloadManager )
{
- if ( d->m_downloadManager != 0 ) {
- d->m_downloadManager->disconnect( this );
- d->m_downloadManager = 0;
- }
-
- d->m_downloadManager = downloadManager;
- if ( d->m_downloadManager != 0 ) {
- connect( d->m_downloadManager, SIGNAL( downloadComplete( QString, QString )),
- SLOT( updateTile( QString, QString )));
- }
-}
-
-void TileLoader::setLayer( GeoSceneLayer * layer )
-{
- // Initialize map theme.
- flush();
- d->m_tileCache.clear();
-
- if ( !layer ) {
- mDebug() << "No layer specified! (GeoSceneLayer * layer = 0)";
- return;
- }
-
- d->m_layer = layer;
-
- TileId id( 0, 0, 0 );
- TextureTile tile( id );
-
- GeoSceneTexture * texture = static_cast<GeoSceneTexture *>( d->m_layer->groundDataset() );
-
- tile.loadDataset( texture );
-
- // We assume that all tiles have the same size. TODO: check to be safe
- d->m_tileWidth = tile.rawtile().width();
- d->m_tileHeight = tile.rawtile().height();
}
void TileLoader::resetTilehash()
@@ -173,40 +146,8 @@ void TileLoader::flush()
d->m_tilesOnDisplay.clear();
}
-int TileLoader::tileWidth() const
-{
- return d->m_tileWidth;
-}
-
-int TileLoader::tileHeight() const
-{
- return d->m_tileHeight;
-}
-
-int TileLoader::globalWidth( int level ) const
+TextureTile* TileLoader::loadTile( TileId const &tileId, bool const forMergedLayerDecorator )
{
- if ( !d->m_layer ) return 0;
-
- GeoSceneTexture * texture = static_cast<GeoSceneTexture *>( d->m_layer->groundDataset() );
-
- return d->m_tileWidth * TileLoaderHelper::levelToColumn(
- texture->levelZeroColumns(), level );
-}
-
-int TileLoader::globalHeight( int level ) const
-{
- if ( !d->m_layer ) return 0;
-
- GeoSceneTexture * texture = static_cast<GeoSceneTexture *>( d->m_layer->groundDataset() );
-
- return d->m_tileHeight * TileLoaderHelper::levelToRow(
- texture->levelZeroRows(), level );
-}
-
-TextureTile* TileLoader::loadTile( TileId const &tileId )
-{
- if ( !d->m_layer ) return 0;
-
// check if the tile is in the hash
TextureTile * tile = d->m_tilesOnDisplay.value( tileId, 0 );
if ( tile ) {
@@ -215,18 +156,15 @@ TextureTile* TileLoader::loadTile( TileId const &tileId )
}
// here ends the performance critical section of this method
+ mDebug() << "TileLoader::loadTile" << tileId.toString();
+
// the tile was not in the hash or has been removed because of expiration
// so check if it is in the cache
tile = d->m_tileCache.take( tileId );
-
- GeoSceneTexture * texture = static_cast<GeoSceneTexture *>( d->m_layer->groundDataset() );
-
if ( tile ) {
// the tile was in the cache, but is it up to date?
- const QDateTime now = QDateTime::currentDateTime();
-
- if ( tile->created().secsTo( now ) < texture->expire()) {
- d->m_tilesOnDisplay[tileId] = tile;
+ if ( !tile->expired() ) {
+ d->m_tilesOnDisplay[ tileId ] = tile;
tile->setUsed( true );
return tile;
} else {
@@ -235,34 +173,53 @@ TextureTile* TileLoader::loadTile( TileId const &tileId )
}
}
+ GeoSceneTexture * const texture = d->m_textureLayers[ tileId.mapThemeIdHash() ];
+
// tile (valid) has not been found in hash or cache, so load it from disk
// and place it in the hash from where it will get transferred to the cache
// mDebug() << "load Tile from Disk: " << tileId.toString();
tile = new TextureTile( tileId );
- d->m_tilesOnDisplay[tileId] = tile;
+ if ( forMergedLayerDecorator )
+ tile->setForMergedLayerDecorator();
+ d->m_tilesOnDisplay[ tileId ] = tile;
- // FIXME: Implement asynchronous tile loading
- // d->m_datasetProvider->loadDatasets( tile );
+ GeoSceneLayer const * const sceneLayer = d->m_sceneLayers.value( tileId.mapThemeIdHash(), 0 );
+ Q_ASSERT( sceneLayer );
+ mDebug() << "scene layer:" << sceneLayer->name();
- if ( d->m_downloadManager != 0 ) {
- connect( tile, SIGNAL( downloadTile( QUrl, QString, QString, DownloadUsage ) ),
- d->m_downloadManager, SLOT( addJob( QUrl, QString, QString, DownloadUsage ) ) );
- }
- tile->loadDataset( texture, &d->m_tileCache );
+ QVector<GeoSceneAbstractDataset*> textureLayers = sceneLayer->datasets();
+ mDebug() << "TileLoader::loadTile: loading base tiles:"
+ << textureLayers.size() << "texture layers found";
- // TODO should emit signal rather than directly calling paintTile
- // emit paintTile( tile, tilx, tily, tileLevel, d->m_theme, false );
- m_parent->paintTile( tile, texture );
+ QVector<GeoSceneAbstractDataset*>::const_iterator pos = textureLayers.constBegin();
+ QVector<GeoSceneAbstractDataset*>::const_iterator const end = textureLayers.constEnd();
+ for (; pos != end; ++pos ) {
+ GeoSceneTexture const * const textureLayer = dynamic_cast<GeoSceneTexture const *>( *pos );
+ if ( !textureLayer )
+ mDebug() << "not a texture layer" << (*pos)->name();
+ if ( textureLayer && ( !textureLayer->hasMaximumTileLevel()
+ || tileId.zoomLevel() <= textureLayer->maximumTileLevel() )) {
+ TileId const simpleTileId( textureLayer->sourceDir(), tileId.zoomLevel(),
+ tileId.x(), tileId.y() );
+ mDebug() << "TileLoader::loadTile: base tile" << textureLayer->sourceDir() << simpleTileId.toString();
+ SimpleTextureTile * const simpleTile = d->m_simpleTileLoader->loadTile( tileId, simpleTileId );
+ // hack to try clouds
+ if ( simpleTile && tile->hasBaseTiles() )
+ simpleTile->setMergeRule( SimpleTextureTile::MergeMultiply );
+ if ( simpleTile )
+ tile->addBaseTile( simpleTile );
+ }
+ }
+ Q_ASSERT( tile->hasBaseTiles() );
+ if ( tile->state() != TextureTile::TileEmpty ) {
+ tile->initResultTile();
+ mergeDecorations( tile, texture );
+ }
return tile;
}
-GeoSceneLayer * TileLoader::layer() const
-{
- return d->m_layer;
-}
-
quint64 TileLoader::volatileCacheLimit() const
{
return d->m_tileCache.maxCost() / 1024;
@@ -281,12 +238,8 @@ QList<TileId> TileLoader::tilesOnDisplay() const
return result;
}
-int TileLoader::maximumTileLevel() const
+int TileLoader::maximumTileLevel( GeoSceneTexture const * const texture )
{
- if ( !d->m_layer )
- return -1;
-
- GeoSceneTexture * texture = static_cast<GeoSceneTexture *>( d->m_layer->groundDataset() );
if ( !texture )
return -1;
@@ -347,39 +300,17 @@ void TileLoader::setVolatileCacheLimit( quint64 kiloBytes )
d->m_tileCache.setMaxCost( kiloBytes * 1024 );
}
-void TileLoader::updateTile( const QByteArray &data, const QString &idStr )
-{
- if ( !d->m_layer )
- return;
-
- const TileId id = TileId::fromString( idStr );
- QHash<TileId, TextureTile*>::iterator pos = d->m_tilesOnDisplay.find( id );
- if ( pos != d->m_tilesOnDisplay.end()) {
- pos.value()->setImage( data );
- GeoSceneTexture * const texture = static_cast<GeoSceneTexture *>( d->m_layer->groundDataset() );
- m_parent->paintTile( pos.value(), texture );
- emit tileUpdateAvailable();
- } else {
- // Remove "false" tile from cache so it doesn't get loaded anymore
- d->m_tileCache.remove( id );
- }
-}
-
-void TileLoader::updateTile( const QString &fileName, const QString &idStr )
+void TileLoader::updateTile( TileId const & composedTileId, TileId const & baseTileId )
{
- if ( !d->m_layer )
- return;
-
- const TileId id = TileId::fromString( idStr );
- if ( d->m_tilesOnDisplay.contains( id ) ) {
- GeoSceneTexture * texture = static_cast<GeoSceneTexture *>( d->m_layer->groundDataset() );
- d->m_tilesOnDisplay[id]->loadDataset( texture, &d->m_tileCache );
- m_parent->paintTile( d->m_tilesOnDisplay[id], texture );
+ TextureTile * const tile = d->m_tilesOnDisplay.value( composedTileId, 0 );
+ if ( tile ) {
+ tile->deriveCompletionState();
+ tile->initResultTile();
+ mergeDecorations( tile, findTextureLayer( composedTileId ));
emit tileUpdateAvailable();
- } else {
- // Remove "false" tile from cache so it doesn't get loaded anymore
- d->m_tileCache.remove( id );
- }
+ } else
+ // TODO: also update tiles in the cache, not doing it is really a waste of i/o
+ d->m_tileCache.remove( composedTileId );
}
void TileLoader::update()
@@ -390,6 +321,66 @@ void TileLoader::update()
emit tileUpdateAvailable();
}
+inline GeoSceneTexture const * TileLoader::findTextureLayer( TileId const & id ) const
+{
+ GeoSceneTexture const * const textureLayer = d->m_textureLayers.value( id.mapThemeIdHash(), 0 );
+ Q_ASSERT( textureLayer );
+ return textureLayer;
+}
+
+inline GeoSceneTexture * TileLoader::findTextureLayer( TileId const & id )
+{
+ GeoSceneTexture * const textureLayer = d->m_textureLayers.value( id.mapThemeIdHash(), 0 );
+ Q_ASSERT( textureLayer );
+ return textureLayer;
+}
+
+void TileLoader::initTextureLayers()
+{
+ QList<GeoSceneDocument const *> const & mapThemes = d->m_mapThemeManager->mapThemes();
+ QList<GeoSceneDocument const *>::const_iterator pos = mapThemes.constBegin();
+ QList<GeoSceneDocument const *>::const_iterator const end = mapThemes.constEnd();
+ for (; pos != end; ++pos ) {
+ GeoSceneHead const * head = (*pos)->head();
+ Q_ASSERT( head );
+ const QString mapThemeId = head->target() + '/' + head->theme();
+ mDebug() << "TileLoader::initTextureLayers" << mapThemeId;
+
+ GeoSceneMap const * map = (*pos)->map();
+ Q_ASSERT( map );
+ GeoSceneLayer const * sceneLayer = map->layer( head->theme() );
+ if ( !sceneLayer ) {
+ mDebug() << "ignoring, has no GeoSceneLayer for" << head->theme();
+ continue;
+ }
+
+ d->m_sceneLayers.insert( qHash( mapThemeId ), sceneLayer );
+
+ // find all texture layers
+ QVector<GeoSceneAbstractDataset *> layers = sceneLayer->datasets();
+ QVector<GeoSceneAbstractDataset *>::const_iterator pos = layers.constBegin();
+ QVector<GeoSceneAbstractDataset *>::const_iterator const end = layers.constEnd();
+ for (; pos != end; ++pos ) {
+ GeoSceneTexture * const textureLayer = dynamic_cast<GeoSceneTexture *>( *pos );
+ if ( !textureLayer ) {
+ mDebug() << "ignoring dataset, is not a texture layer";
+ continue;
+ }
+ d->m_textureLayers.insert( qHash( textureLayer->sourceDir() ), textureLayer );
+ mDebug() << "TileLoader::initTextureLayers" << "added texture layer:"
+ << qHash( textureLayer->sourceDir() ) << textureLayer->sourceDir();
+ }
+ }
+}
+
+void TileLoader::mergeDecorations( TextureTile * const tile,
+ GeoSceneTexture * const textureLayer ) const
+{
+ Q_ASSERT( tile->state() != TextureTile::TileEmpty );
+ if ( !tile->forMergedLayerDecorator() )
+ m_parent->paintTile( tile, textureLayer );
+}
+
}
#include "TileLoader.moc"
diff --git a/marble/src/lib/TileLoader.h b/marble/src/lib/TileLoader.h
index bda81de..ae0c7fc 100644
--- a/marble/src/lib/TileLoader.h
+++ b/marble/src/lib/TileLoader.h
@@ -35,8 +35,10 @@ namespace Marble
class TextureTile;
class HttpDownloadManager;
+class MapThemeManager;
class MarbleModel;
class GeoSceneLayer;
+class GeoSceneTexture;
class TileLoaderPrivate;
@@ -64,11 +66,8 @@ class TileLoader : public QObject
* @param downloadManager The download manager that shall be used to fetch
* the tiles from a remote resource.
*/
- TileLoader( HttpDownloadManager *downloadManager, MarbleModel* parent);
-
- /**
- * Destroys the tile loader.
- */
+ TileLoader( MapThemeManager const * const mapThemeManager,
+ HttpDownloadManager * const downloadManager, MarbleModel * const model );
virtual ~TileLoader();
/**
@@ -82,17 +81,7 @@ class TileLoader : public QObject
*
* @param tileId The Id of the requested tile, containing the x and y coordinate and the zoom level.
*/
- TextureTile* loadTile( TileId const &tileId );
-
- /**
- * Sets the texture layer @p the tiles shall be loaded for.
- */
- void setLayer( GeoSceneLayer * layer );
-
- /**
- * Returns the texture layer the tiles shall be loaded for.
- */
- GeoSceneLayer * layer() const;
+ TextureTile* loadTile( TileId const &tileId, bool const forMergedLayerDecorator = false );
/**
* Resets the internal tile hash.
@@ -114,26 +103,6 @@ class TileLoader : public QObject
void flush();
/**
- * Returns the width of a tile loaded by this tile loader.
- */
- int tileWidth() const;
-
- /**
- * Returns the height of a tile loaded by this tile loader.
- */
- int tileHeight() const;
-
- /**
- * Returns the global width for the given @p level.
- */
- int globalWidth( int level ) const;
-
- /**
- * Returns the global height for the given @p level.
- */
- int globalHeight( int level ) const;
-
- /**
* @brief Returns the limit of the volatile (in RAM) cache.
* @return the cache limit in kilobytes
*/
@@ -150,7 +119,7 @@ class TileLoader : public QObject
* Returns the highest level in which some tiles are theoretically
* available for the given @p texture layer.
*/
- int maximumTileLevel() const;
+ static int maximumTileLevel( GeoSceneTexture const * const textureLayer );
/**
* Returns whether the mandatory most basic tile level is fully available for
@@ -165,9 +134,9 @@ class TileLoader : public QObject
*/
void setVolatileCacheLimit( quint64 kiloBytes );
- void updateTile( const QByteArray &data, const QString &id );
-
- void updateTile( const QString &fileName, const QString &id );
+ /**
+ */
+ void updateTile( TileId const & composedTileId, TileId const & baseTileId );
/**
* Effectively triggers a reload of all tiles that are currently in use
@@ -181,13 +150,13 @@ class TileLoader : public QObject
* downloaded and is available now.
*/
void tileUpdateAvailable();
-
- void paintTile(TextureTile* tile, int x, int y, int level,
- GeoSceneLayer * layer,
- bool requestTileUpdate);
private:
Q_DISABLE_COPY( TileLoader )
+ GeoSceneTexture const * findTextureLayer( TileId const & ) const;
+ GeoSceneTexture * findTextureLayer( TileId const & );
+ void initTextureLayers();
+ void mergeDecorations( TextureTile * const, GeoSceneTexture * const ) const;
TileLoaderPrivate* const d;
MarbleModel* m_parent;
diff --git a/marble/src/lib/TileLoaderHelper.cpp b/marble/src/lib/TileLoaderHelper.cpp
index 7818404..6c09934 100644
--- a/marble/src/lib/TileLoaderHelper.cpp
+++ b/marble/src/lib/TileLoaderHelper.cpp
@@ -105,8 +105,8 @@ QUrl TileLoaderHelper::downloadUrl( GeoSceneTexture *textureLayer, int zoomLevel
return tileUrl;
}
-QString TileLoaderHelper::relativeTileFileName( GeoSceneTexture *textureLayer, int level, int x,
- int y )
+QString TileLoaderHelper::relativeTileFileName( GeoSceneTexture const * const textureLayer,
+ int level, int x, int y )
{
QString relFileName;
if ( textureLayer ) {
@@ -142,7 +142,7 @@ QString TileLoaderHelper::relativeTileFileName( GeoSceneTexture *textureLayer, i
return relFileName;
}
-QString TileLoaderHelper::themeStr( GeoSceneTexture *textureLayer )
+QString TileLoaderHelper::themeStr( GeoSceneTexture const * const textureLayer )
{
QString oldThemeStr;
diff --git a/marble/src/lib/TileLoaderHelper.h b/marble/src/lib/TileLoaderHelper.h
index 9ba4d16..a48740b 100644
--- a/marble/src/lib/TileLoaderHelper.h
+++ b/marble/src/lib/TileLoaderHelper.h
@@ -87,7 +87,7 @@ namespace TileLoaderHelper
/**
* @brief Get the relative file name of a tile.
*/
- QString relativeTileFileName( GeoSceneTexture *textureLayer, int zoomLevel, int x, int y );
+ QString relativeTileFileName( GeoSceneTexture const * const textureLayer, int zoomLevel, int x, int y );
/**
* @brief Get the theme string
@@ -95,7 +95,7 @@ namespace TileLoaderHelper
* @return the old style theme string which used to be the argument for many methods,
* for example "maps/earth/srtm".
*/
- QString themeStr( GeoSceneTexture *textureLayer );
+ QString themeStr( GeoSceneTexture const * const textureLayer );
}
}
diff --git a/marble/src/lib/geodata/scene/GeoSceneMap.cpp b/marble/src/lib/geodata/scene/GeoSceneMap.cpp
index c580f4e..f9b83e9 100644
--- a/marble/src/lib/geodata/scene/GeoSceneMap.cpp
+++ b/marble/src/lib/geodata/scene/GeoSceneMap.cpp
@@ -109,6 +109,21 @@ GeoSceneLayer* GeoSceneMap::layer( const QString& name )
return layer;
}
+const GeoSceneLayer* GeoSceneMap::layer( const QString& name ) const
+{
+ const GeoSceneLayer* layer = 0;
+
+ QVector<GeoSceneLayer*>::const_iterator it = d->m_layers.constBegin();
+ QVector<GeoSceneLayer*>::const_iterator end = d->m_layers.constEnd();
+ for (; it != end; ++it) {
+ if ( (*it)->name() == name ) {
+ layer = *it;
+ break;
+ }
+ }
+ return layer;
+}
+
QVector<GeoSceneLayer*> GeoSceneMap::layers() const
{
return d->m_layers;
diff --git a/marble/src/lib/geodata/scene/GeoSceneMap.h b/marble/src/lib/geodata/scene/GeoSceneMap.h
index 88fb045..8668483 100644
--- a/marble/src/lib/geodata/scene/GeoSceneMap.h
+++ b/marble/src/lib/geodata/scene/GeoSceneMap.h
@@ -65,6 +65,7 @@ class GEODATA_EXPORT GeoSceneMap : public GeoNode
* @return A pointer to the layer request by its name
*/
GeoSceneLayer* layer( const QString& name );
+ const GeoSceneLayer* layer( const QString& name ) const;
/**
* @brief Return all layers
diff --git a/marble/src/lib/geodata/scene/GeoSceneTexture.h b/marble/src/lib/geodata/scene/GeoSceneTexture.h
index fea700d..af28c44 100644
--- a/marble/src/lib/geodata/scene/GeoSceneTexture.h
+++ b/marble/src/lib/geodata/scene/GeoSceneTexture.h
@@ -66,6 +66,7 @@ class GeoSceneTexture : public GeoSceneAbstractDataset
int levelZeroRows() const;
void setLevelZeroRows( const int );
+ bool hasMaximumTileLevel() const;
int maximumTileLevel() const;
void setMaximumTileLevel( const int );
@@ -104,6 +105,11 @@ class GeoSceneTexture : public GeoSceneAbstractDataset
QList<DownloadPolicy *> m_downloadPolicies;
};
+inline bool GeoSceneTexture::hasMaximumTileLevel() const
+{
+ return m_maximumTileLevel != -1;
+}
+
}
#endif // GEOSCENETEXTURE_H
More information about the Marble-devel
mailing list