QImage TileLoader::scaledLowerLevelTile( const GeoSceneTextureTile * textureLayer, TileId const & id ) { mDebug() << Q_FUNC_INFO << id; for ( int level = qMax<int>( 0, id.zoomLevel() - 1 ); level >= 0; --level ) { int const deltaLevel = id.zoomLevel() - level; TileId const replacementTileId( id.mapThemeIdHash(), level, id.x() >> deltaLevel, id.y() >> deltaLevel ); QString const fileName = tileFileName( textureLayer, replacementTileId ); mDebug() << "TileLoader::scaledLowerLevelTile" << "trying" << fileName; QImage toScale = QFile::exists(fileName) ? QImage(fileName) : QImage(); if ( level == 0 && toScale.isNull() ) { mDebug() << "No level zero tile installed in map theme dir. Falling back to a transparent image for now."; QSize tileSize = textureLayer->tileSize(); Q_ASSERT( !tileSize.isEmpty() ); // assured by textureLayer toScale = QImage( tileSize, QImage::Format_ARGB32_Premultiplied ); toScale.fill( qRgba( 0, 0, 0, 0 ) ); } if ( !toScale.isNull() ) { // which rect to scale? int const restTileX = id.x() % ( 1 << deltaLevel ); int const restTileY = id.y() % ( 1 << deltaLevel ); int const partWidth = qMax(1, toScale.width() >> deltaLevel); int const partHeight = qMax(1, 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(); return part.scaled( toScale.size() ); } }
GeoDataDocument *TileLoader::loadTileVectorData( GeoSceneVectorTileDataset const *textureLayer, TileId const & tileId, DownloadUsage const usage ) { // FIXME: textureLayer->fileFormat() could be used in the future for use just that parser, instead of all available parsers QString const fileName = tileFileName( textureLayer, tileId ); TileStatus status = tileStatus( textureLayer, tileId ); if ( status != Missing ) { // check if an update should be triggered if ( status == Available ) { mDebug() << Q_FUNC_INFO << tileId << "StateUptodate"; } else { Q_ASSERT( status == Expired ); mDebug() << Q_FUNC_INFO << tileId << "StateExpired"; triggerDownload( textureLayer, tileId, usage ); } QFile file ( fileName ); if ( file.exists() ) { // File is ready, so parse and return the vector data in any case GeoDataDocument* document = openVectorFile(fileName); if (document) { return document; } } } // tile was not locally available => trigger download triggerDownload( textureLayer, tileId, usage ); return nullptr; }
TileLoader::TileStatus TileLoader::tileStatus( GeoSceneTiled const *textureLayer, const TileId &tileId ) { QString const fileName = tileFileName( textureLayer, tileId ); QFileInfo fileInfo( fileName ); if ( !fileInfo.exists() ) { return Missing; } const QDateTime lastModified = fileInfo.lastModified(); const int expireSecs = textureLayer->expire(); const bool isExpired = lastModified.secsTo( QDateTime::currentDateTime() ) >= expireSecs; return isExpired ? Expired : Available; }
bool TileLoader::baseTilesAvailable( GeoSceneTiled const & texture ) { const int levelZeroColumns = texture.levelZeroColumns(); const int levelZeroRows = texture.levelZeroRows(); bool result = true; // Check whether the tiles from the lowest texture level are available // for ( int column = 0; result && column < levelZeroColumns; ++column ) { for ( int row = 0; result && row < levelZeroRows; ++row ) { const TileId id( 0, 0, column, row ); const QString tilepath = tileFileName( &texture, id ); result &= QFile::exists( tilepath ); if (!result) { mDebug() << "Base tile " << texture.relativeTileFileName( id ) << " is missing for source dir " << texture.sourceDir(); } } } return result; }