istereo2
view libs/goatkit/theme.cc @ 9:64e15874f3bd
foo
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 26 Sep 2015 02:56:07 +0300 |
parents | a3c4fcc9f8f3 |
children | 03cc3b1884d1 |
line source
1 /*
2 GoatKit - a themable/animated widget toolkit for games
3 Copyright (C) 2014-2015 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "config.h"
19 #include <stdio.h>
20 #include <vector>
21 #include <string>
22 #include <map>
23 #include <algorithm>
24 #include <string.h>
25 #include "theme.h"
26 #include "widget.h"
28 #ifdef WIN32
29 #include <windows.h>
31 #define RTLD_DEFAULT ((void*)0)
33 static void *dlopen(const char *name, int flags);
34 static void dlclose(void *so);
35 static void *dlsym(void *so, const char *symbol);
36 #else
37 #include <unistd.h>
38 #include <dlfcn.h>
39 #endif
41 #ifdef HAVE_OPENGL_H
42 #include "opengl.h"
44 #else
46 #ifdef __APPLE__
47 #include <OpenGL/gl.h>
48 #else
49 #include <GL/gl.h>
50 #endif
52 #endif /* HAVE_OPENGL_H_ */
54 #ifndef PREFIX
55 #define PREFIX "/usr/local"
56 #endif
58 namespace goatkit {
60 struct ThemeImpl {
61 void *so;
62 WidgetDrawFunc (*lookup_theme_draw_func)(const char*);
63 mutable std::map<std::string, WidgetDrawFunc> func_cache;
64 };
66 Theme *theme;
67 static std::vector<std::string> search_paths;
68 static const char *fallback_paths[] = {
69 PREFIX "/share/goatkit",
70 0
71 };
73 void add_theme_path(const char *path)
74 {
75 if(!path || !*path) return;
77 std::string s = path;
78 int last = s.length() - 1;
79 if(s[last] == '/' || s[last] == '\\') {
80 s.erase(last);
81 }
83 if(std::find(search_paths.begin(), search_paths.end(), s) != search_paths.end()) {
84 return;
85 }
87 search_paths.push_back(s);
88 }
90 Theme::Theme()
91 {
92 impl = new ThemeImpl;
93 impl->so = 0;
94 impl->lookup_theme_draw_func = 0;
95 }
97 Theme::~Theme()
98 {
99 unload();
100 delete impl;
101 }
103 typedef WidgetDrawFunc (*LookupFunc)(const char*);
105 bool Theme::load(const char *name)
106 {
107 unload();
109 if(strcmp(name, "GOATKIT_THEME_BUILTIN") == 0) {
110 impl->so = RTLD_DEFAULT;
111 } else {
112 std::string fname = std::string(name) + ".gtheme";
113 if(!(impl->so = dlopen(fname.c_str(), RTLD_LAZY))) {
114 for(size_t i=0; i<search_paths.size(); i++) {
115 std::string path = search_paths[i] + "/" + fname;
117 if((impl->so = dlopen(path.c_str(), RTLD_LAZY))) {
118 break;
119 }
120 }
122 // try the fallback paths
123 if(!impl->so) {
124 for(int i=0; fallback_paths[i]; i++) {
125 std::string path = std::string(fallback_paths[i]) + "/" + fname;
127 if((impl->so = dlopen(path.c_str(), RTLD_LAZY))) {
128 break;
129 }
130 }
131 }
133 if(!impl->so) {
134 fprintf(stderr, "%s: failed to load theme plugin: %s\n", __func__, name);
135 return false;
136 }
137 }
138 }
140 // loaded the shared object, now get the lookup function
141 impl->lookup_theme_draw_func = (LookupFunc)dlsym(impl->so, "get_widget_func");
142 if(!impl->lookup_theme_draw_func) {
143 fprintf(stderr, "%s: invalid theme plugin %s\n", __func__, name);
144 unload();
145 return false;
146 }
148 return true;
149 }
151 void Theme::unload()
152 {
153 if(impl->so) {
154 if(impl->so != RTLD_DEFAULT) {
155 dlclose(impl->so);
156 }
157 impl->so = 0;
158 }
159 impl->func_cache.clear();
160 }
162 WidgetDrawFunc Theme::get_draw_func(const char *type) const
163 {
164 std::map<std::string, WidgetDrawFunc>::const_iterator it = impl->func_cache.find(type);
165 if(it == impl->func_cache.end()) {
166 // don't have it cached, try to look it up
167 WidgetDrawFunc func;
168 if(impl->lookup_theme_draw_func && (func = impl->lookup_theme_draw_func(type))) {
169 impl->func_cache[type] = func;
170 return func;
171 }
173 // can't look it up, return the default
174 return default_draw_func;
175 }
176 return it->second;
177 }
179 #define LERP(a, b, t) ((a) + ((b) - (a)) * t)
180 #define DEF_TEX_SZ 32
181 void default_draw_func(const Widget *w)
182 {
183 static unsigned int tex;
185 if(!tex) {
186 unsigned char *pixels = new unsigned char[DEF_TEX_SZ * DEF_TEX_SZ * 3];
187 unsigned char *ptr = pixels;
188 for(int i=0; i<DEF_TEX_SZ; i++) {
189 for(int j=0; j<DEF_TEX_SZ; j++) {
190 bool stripe = (((j + i) / 8) & 1) == 1;
191 ptr[0] = ptr[1] = ptr[2] = stripe ? 255 : 0;
192 ptr += 3;
193 }
194 }
196 glGenTextures(1, &tex);
197 glBindTexture(GL_TEXTURE_2D, tex);
198 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
199 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
200 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, DEF_TEX_SZ, DEF_TEX_SZ, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
201 delete [] pixels;
202 }
204 Vec2 pos = w->get_position();
205 Vec2 sz = w->get_size();
206 float aspect = sz.x / sz.y;
208 #if !defined(GL_ES_VERSION_2_0)
209 glPushAttrib(GL_ENABLE_BIT);
210 glEnable(GL_TEXTURE_2D);
211 #endif
212 glBindTexture(GL_TEXTURE_2D, tex);
214 float offs = w->get_pressed() * 0.1 * sz.y;
215 glMatrixMode(GL_MODELVIEW);
216 glPushMatrix();
217 glTranslatef(offs, -offs, 0);
219 float active = w->get_active();
220 float hover = w->get_under_mouse();
222 float rg = LERP(0.4, 1.0, hover);
223 float b = LERP(rg, 0, active);
224 glColor3f(rg, rg, b);
226 glBegin(GL_QUADS);
227 glTexCoord2f(0, 1);
228 glVertex2f(pos.x, pos.y);
229 glTexCoord2f(aspect, 1);
230 glVertex2f(pos.x + sz.x, pos.y);
231 glTexCoord2f(aspect, 0);
232 glVertex2f(pos.x + sz.x, pos.y + sz.y);
233 glTexCoord2f(0, 0);
234 glVertex2f(pos.x, pos.y + sz.y);
235 glEnd();
237 glPopMatrix();
239 #ifndef GL_ES_VERSION_2_0
240 glPopAttrib();
241 #endif
242 }
244 } // namespace goatkit
246 #ifdef WIN32
247 // XXX untested
248 static void *dlopen(const char *name, int flags)
249 {
250 return LoadLibrary(name);
251 }
253 static void dlclose(void *so)
254 {
255 FreeLibrary(so);
256 }
258 static void *dlsym(void *so, const char *symbol)
259 {
260 if(so == RTLD_DEFAULT) {
261 so = GetModuleHandle(0);
262 }
263 return (void*)GetProcAddress(so, symbol);
264 }
265 #endif