Warning, file /education/kstars/kstars/texturemanager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2010 Henry de Valence <hdevalence@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "texturemanager.h" 0008 0009 #include "kspaths.h" 0010 #include "auxiliary/kspaths.h" 0011 0012 #ifdef KSTARS_LITE 0013 #include <QStandardPaths> 0014 #include <QImage> 0015 #else 0016 #include "skymap.h" 0017 #include "kstars.h" 0018 #endif 0019 0020 #ifdef HAVE_OPENGL 0021 #include <QGLWidget> 0022 #endif 0023 0024 // We returning reference to image. We refer to this image when search 0025 // for image fails 0026 const static QImage emptyImage; 0027 0028 TextureManager *TextureManager::m_p = nullptr; 0029 0030 TextureManager *TextureManager::Create() 0031 { 0032 if (!m_p) 0033 { 0034 m_p = new TextureManager(); 0035 discoverTextureDirs(); 0036 } 0037 return m_p; 0038 } 0039 0040 void TextureManager::Release() 0041 { 0042 delete m_p; 0043 m_p = nullptr; 0044 } 0045 0046 const QImage &TextureManager::getImage(const QString &name) 0047 { 0048 Create(); 0049 if (name.isEmpty()) 0050 return emptyImage; 0051 CacheIter it = findTexture(name); 0052 if (it != m_p->m_textures.constEnd()) 0053 { 0054 return *it; 0055 } 0056 else 0057 { 0058 return emptyImage; 0059 } 0060 } 0061 0062 TextureManager::CacheIter TextureManager::findTexture(const QString &name) 0063 { 0064 Create(); 0065 // Lookup in cache first 0066 CacheIter it = m_p->m_textures.constFind(name); 0067 if (it != m_p->m_textures.constEnd()) 0068 { 0069 return it; 0070 } 0071 0072 for (const auto &dir : m_p->m_texture_directories) 0073 { 0074 const auto &filename = QString("%1/%2.png").arg(dir).arg(name); 0075 QFile file{ filename }; 0076 if (file.exists()) 0077 return (TextureManager::CacheIter)m_p->m_textures.insert( 0078 name, QImage(filename, "PNG")); 0079 } 0080 0081 //Try to load from the file in 'skycultures/western' subdirectory for western constellation art 0082 QString filename = KSPaths::locate(QStandardPaths::AppLocalDataLocation, 0083 QString("skycultures/western/%1.png").arg(name)); 0084 if (!filename.isNull()) 0085 { 0086 return (TextureManager::CacheIter)m_p->m_textures.insert(name, 0087 QImage(filename, "PNG")); 0088 } 0089 0090 //Try to load from the file in 'skycultures/inuit' subdirectory for Inuit constellation art 0091 filename = KSPaths::locate(QStandardPaths::AppLocalDataLocation, 0092 QString("skycultures/inuit/%1.png").arg(name)); 0093 if (!filename.isNull()) 0094 { 0095 return (TextureManager::CacheIter)m_p->m_textures.insert(name, 0096 QImage(filename, "PNG")); 0097 } 0098 0099 // Try to load from file in main data directory 0100 filename = KSPaths::locate(QStandardPaths::AppLocalDataLocation, 0101 QString("textures/%1.png").arg(name)); 0102 0103 if (!filename.isNull()) 0104 { 0105 return (TextureManager::CacheIter)m_p->m_textures.insert(name, 0106 QImage(filename, "PNG")); 0107 } 0108 0109 return (TextureManager::CacheIter)m_p->m_textures.insert(name, QImage()); 0110 } 0111 0112 #ifdef HAVE_OPENGL 0113 static void bindImage(const QImage &img, QGLWidget *cxt) 0114 { 0115 GLuint tid = cxt->bindTexture(img, GL_TEXTURE_2D, GL_RGBA, QGLContext::DefaultBindOption); 0116 glBindTexture(GL_TEXTURE_2D, tid); 0117 } 0118 0119 // FIXME: should we check that image have appropriate size as bindFromImage do? 0120 void TextureManager::bindTexture(const QString &name, QGLWidget *cxt) 0121 { 0122 Create(); 0123 Q_ASSERT("Must be called only with valid GL context" && cxt); 0124 0125 CacheIter it = findTexture(name); 0126 if (it != m_p->m_textures.constEnd()) 0127 bindImage(*it, cxt); 0128 } 0129 0130 void TextureManager::bindFromImage(const QImage &image, QGLWidget *cxt) 0131 { 0132 Create(); 0133 Q_ASSERT("Must be called only with valid GL context" && cxt); 0134 0135 if (image.width() != image.height() || (image.width() & (image.width() - 1))) 0136 { 0137 // Compute texture size 0138 int longest = qMax(image.width(), image.height()); 0139 int tex_size = 2; 0140 while (tex_size < longest) 0141 { 0142 tex_size *= 2; 0143 } 0144 // FIXME: Check if Qt does this for us already. [Note that it does scale to the nearest power of two] 0145 bindImage(image.scaled(tex_size, tex_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), cxt); 0146 } 0147 else 0148 { 0149 bindImage(image, cxt); 0150 } 0151 } 0152 #endif 0153 0154 TextureManager::TextureManager(QObject *parent) : QObject(parent) {} 0155 0156 void TextureManager::discoverTextureDirs() 0157 { 0158 // clear the cache 0159 m_p->m_textures = {}; 0160 0161 const auto &base = KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation); 0162 QDirIterator search(base, QStringList() << "textures_*", QDir::Dirs); 0163 0164 auto &dirs = m_p->m_texture_directories; 0165 while (search.hasNext()) 0166 { 0167 dirs.push_back(search.next()); 0168 } 0169 0170 dirs.push_back(base); 0171 };