Kstars

texturemanager.cpp
1/*
2 SPDX-FileCopyrightText: 2010 Henry de Valence <hdevalence@gmail.com>
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
28const static QImage emptyImage;
29
30TextureManager *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
64TextureManager::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
115static 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?
122void 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
132void 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
156TextureManager::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};
a singleton class to manage texture loading/retrieval
static const QImage & getImage(const QString &name)
Return texture image.
static void discoverTextureDirs()
Clear the cache and discover the directories to load textures from.
static void Release()
Release the instance of TextureManager.
static TextureManager * Create()
Create the instance of TextureManager.
bool hasNext() const const
QString next()
const_iterator constEnd() const const
const_iterator constFind(const Key &key) const const
iterator insert(const Key &key, const T &value)
int height() const const
QImage scaled(const QSize &size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
int width() const const
QString arg(Args &&... args) const const
bool isEmpty() const const
bool isNull() const const
IgnoreAspectRatio
SmoothTransformation
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:38:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.