Kstars

texturemanager.cpp
1 /*
2  SPDX-FileCopyrightText: 2010 Henry de Valence <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "texturemanager.h"
8 
9 #include "kspaths.h"
10 #include "auxiliary/kspaths.h"
11 
12 #include <QDirIterator>
13 
14 #ifdef KSTARS_LITE
15 #include <QStandardPaths>
16 #include <QImage>
17 #else
18 #include "skymap.h"
19 #include "kstars.h"
20 #endif
21 
22 #ifdef HAVE_OPENGL
23 #include <QGLWidget>
24 #endif
25 
26 // We returning reference to image. We refer to this image when search
27 // for image fails
28 const static QImage emptyImage;
29 
30 TextureManager *TextureManager::m_p = nullptr;
31 
33 {
34  if (!m_p)
35  {
36  m_p = new TextureManager();
38  }
39  return m_p;
40 }
41 
43 {
44  delete m_p;
45  m_p = nullptr;
46 }
47 
49 {
50  Create();
51  if (name.isEmpty())
52  return emptyImage;
53  CacheIter it = findTexture(name);
54  if (it != m_p->m_textures.constEnd())
55  {
56  return *it;
57  }
58  else
59  {
60  return emptyImage;
61  }
62 }
63 
64 TextureManager::CacheIter TextureManager::findTexture(const QString &name)
65 {
66  Create();
67  // Lookup in cache first
68  CacheIter it = m_p->m_textures.constFind(name);
69  if (it != m_p->m_textures.constEnd())
70  {
71  return it;
72  }
73 
74  for (const auto &dir : m_p->m_texture_directories)
75  {
76  const auto &filename = QString("%1/%2.png").arg(dir).arg(name);
77  QFile file{ filename };
78  if (file.exists())
79  return (TextureManager::CacheIter)m_p->m_textures.insert(
80  name, QImage(filename, "PNG"));
81  }
82 
83  //Try to load from the file in 'skycultures/western' subdirectory for western constellation art
84  QString filename = KSPaths::locate(QStandardPaths::AppLocalDataLocation,
85  QString("skycultures/western/%1.png").arg(name));
86  if (!filename.isNull())
87  {
88  return (TextureManager::CacheIter)m_p->m_textures.insert(name,
89  QImage(filename, "PNG"));
90  }
91 
92  //Try to load from the file in 'skycultures/inuit' subdirectory for Inuit constellation art
93  filename = KSPaths::locate(QStandardPaths::AppLocalDataLocation,
94  QString("skycultures/inuit/%1.png").arg(name));
95  if (!filename.isNull())
96  {
97  return (TextureManager::CacheIter)m_p->m_textures.insert(name,
98  QImage(filename, "PNG"));
99  }
100 
101  // Try to load from file in main data directory
102  filename = KSPaths::locate(QStandardPaths::AppLocalDataLocation,
103  QString("textures/%1.png").arg(name));
104 
105  if (!filename.isNull())
106  {
107  return (TextureManager::CacheIter)m_p->m_textures.insert(name,
108  QImage(filename, "PNG"));
109  }
110 
111  return (TextureManager::CacheIter)m_p->m_textures.insert(name, QImage());
112 }
113 
114 #ifdef HAVE_OPENGL
115 static void bindImage(const QImage &img, QGLWidget *cxt)
116 {
117  GLuint tid = cxt->bindTexture(img, GL_TEXTURE_2D, GL_RGBA, QGLContext::DefaultBindOption);
118  glBindTexture(GL_TEXTURE_2D, tid);
119 }
120 
121 // FIXME: should we check that image have appropriate size as bindFromImage do?
122 void TextureManager::bindTexture(const QString &name, QGLWidget *cxt)
123 {
124  Create();
125  Q_ASSERT("Must be called only with valid GL context" && cxt);
126 
127  CacheIter it = findTexture(name);
128  if (it != m_p->m_textures.constEnd())
129  bindImage(*it, cxt);
130 }
131 
132 void TextureManager::bindFromImage(const QImage &image, QGLWidget *cxt)
133 {
134  Create();
135  Q_ASSERT("Must be called only with valid GL context" && cxt);
136 
137  if (image.width() != image.height() || (image.width() & (image.width() - 1)))
138  {
139  // Compute texture size
140  int longest = qMax(image.width(), image.height());
141  int tex_size = 2;
142  while (tex_size < longest)
143  {
144  tex_size *= 2;
145  }
146  // FIXME: Check if Qt does this for us already. [Note that it does scale to the nearest power of two]
147  bindImage(image.scaled(tex_size, tex_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), cxt);
148  }
149  else
150  {
151  bindImage(image, cxt);
152  }
153 }
154 #endif
155 
156 TextureManager::TextureManager(QObject *parent) : QObject(parent) {}
157 
159 {
160  // clear the cache
161  m_p->m_textures = {};
162 
163  const auto &base = KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
164  QDirIterator search(base, QStringList() << "textures_*", QDir::Dirs);
165 
166  auto &dirs = m_p->m_texture_directories;
167  while (search.hasNext())
168  {
169  dirs.push_back(search.next());
170  }
171 
172  dirs.push_back(base);
173 };
bool isNull() const const
int height() const const
bool hasNext() const const
QImage scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
QString next()
GLuint bindTexture(const QImage &image, GLenum target, GLint format, QGLContext::BindOptions options)
QHash::iterator insert(const Key &key, const T &value)
IgnoreAspectRatio
QHash::const_iterator constEnd() const const
a singleton class to manage texture loading/retrieval
QHash::const_iterator constFind(const Key &key) const const
static TextureManager * Create()
Create the instance of TextureManager.
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
KStandardDirs * dirs()
static const QImage & getImage(const QString &name)
Return texture image.
SmoothTransformation
static void Release()
Release the instance of TextureManager.
static void discoverTextureDirs()
Clear the cache and discover the directories to load textures from.
int width() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sat Sep 30 2023 04:02:47 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.