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 #ifdef KSTARS_LITE
13 #include <QStandardPaths>
14 #include <QImage>
15 #else
16 #include "skymap.h"
17 #include "kstars.h"
18 #endif
19 
20 #ifdef HAVE_OPENGL
21 #include <QGLWidget>
22 #endif
23 
24 // We returning reference to image. We refer to this image when search
25 // for image fails
26 const static QImage emptyImage;
27 
28 TextureManager *TextureManager::m_p = nullptr;
29 
31 {
32  if (!m_p)
33  {
34  m_p = new TextureManager();
36  }
37  return m_p;
38 }
39 
41 {
42  delete m_p;
43  m_p = nullptr;
44 }
45 
47 {
48  Create();
49  if (name.isEmpty())
50  return emptyImage;
51  CacheIter it = findTexture(name);
52  if (it != m_p->m_textures.constEnd())
53  {
54  return *it;
55  }
56  else
57  {
58  return emptyImage;
59  }
60 }
61 
62 TextureManager::CacheIter TextureManager::findTexture(const QString &name)
63 {
64  Create();
65  // Lookup in cache first
66  CacheIter it = m_p->m_textures.constFind(name);
67  if (it != m_p->m_textures.constEnd())
68  {
69  return it;
70  }
71 
72  for (const auto &dir : m_p->m_texture_directories)
73  {
74  const auto &filename = QString("%1/%2.png").arg(dir).arg(name);
75  QFile file{ filename };
76  if (file.exists())
77  return (TextureManager::CacheIter)m_p->m_textures.insert(
78  name, QImage(filename, "PNG"));
79  }
80 
81  //Try to load from the file in 'skycultures/western' subdirectory for western constellation art
82  QString filename = KSPaths::locate(QStandardPaths::AppLocalDataLocation,
83  QString("skycultures/western/%1.png").arg(name));
84  if (!filename.isNull())
85  {
86  return (TextureManager::CacheIter)m_p->m_textures.insert(name,
87  QImage(filename, "PNG"));
88  }
89 
90  //Try to load from the file in 'skycultures/inuit' subdirectory for Inuit constellation art
91  filename = KSPaths::locate(QStandardPaths::AppLocalDataLocation,
92  QString("skycultures/inuit/%1.png").arg(name));
93  if (!filename.isNull())
94  {
95  return (TextureManager::CacheIter)m_p->m_textures.insert(name,
96  QImage(filename, "PNG"));
97  }
98 
99  // Try to load from file in main data directory
100  filename = KSPaths::locate(QStandardPaths::AppLocalDataLocation,
101  QString("textures/%1.png").arg(name));
102 
103  if (!filename.isNull())
104  {
105  return (TextureManager::CacheIter)m_p->m_textures.insert(name,
106  QImage(filename, "PNG"));
107  }
108 
109  return (TextureManager::CacheIter)m_p->m_textures.insert(name, QImage());
110 }
111 
112 #ifdef HAVE_OPENGL
113 static void bindImage(const QImage &img, QGLWidget *cxt)
114 {
115  GLuint tid = cxt->bindTexture(img, GL_TEXTURE_2D, GL_RGBA, QGLContext::DefaultBindOption);
116  glBindTexture(GL_TEXTURE_2D, tid);
117 }
118 
119 // FIXME: should we check that image have appropriate size as bindFromImage do?
120 void TextureManager::bindTexture(const QString &name, QGLWidget *cxt)
121 {
122  Create();
123  Q_ASSERT("Must be called only with valid GL context" && cxt);
124 
125  CacheIter it = findTexture(name);
126  if (it != m_p->m_textures.constEnd())
127  bindImage(*it, cxt);
128 }
129 
130 void TextureManager::bindFromImage(const QImage &image, QGLWidget *cxt)
131 {
132  Create();
133  Q_ASSERT("Must be called only with valid GL context" && cxt);
134 
135  if (image.width() != image.height() || (image.width() & (image.width() - 1)))
136  {
137  // Compute texture size
138  int longest = qMax(image.width(), image.height());
139  int tex_size = 2;
140  while (tex_size < longest)
141  {
142  tex_size *= 2;
143  }
144  // FIXME: Check if Qt does this for us already. [Note that it does scale to the nearest power of two]
145  bindImage(image.scaled(tex_size, tex_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), cxt);
146  }
147  else
148  {
149  bindImage(image, cxt);
150  }
151 }
152 #endif
153 
154 TextureManager::TextureManager(QObject *parent) : QObject(parent) {}
155 
157 {
158  // clear the cache
159  m_p->m_textures = {};
160 
161  const auto &base = KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
162  QDirIterator search(base, QStringList() << "textures_*", QDir::Dirs);
163 
164  auto &dirs = m_p->m_texture_directories;
165  while (search.hasNext())
166  {
167  dirs.push_back(search.next());
168  }
169 
170  dirs.push_back(base);
171 };
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
bool isEmpty() 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
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-2022 The KDE developers.
Generated on Sat Aug 13 2022 04:02:00 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.