istereo2
diff libs/goatkit/theme.cc @ 6:3bccfc7d10fe
goatkit is drawing
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 23 Sep 2015 05:44:58 +0300 |
parents | |
children | a3c4fcc9f8f3 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/goatkit/theme.cc Wed Sep 23 05:44:58 2015 +0300 1.3 @@ -0,0 +1,253 @@ 1.4 +/* 1.5 +GoatKit - a themable/animated widget toolkit for games 1.6 +Copyright (C) 2014 John Tsiombikas <nuclear@member.fsf.org> 1.7 + 1.8 +This program is free software: you can redistribute it and/or modify 1.9 +it under the terms of the GNU Lesser General Public License as published by 1.10 +the Free Software Foundation, either version 3 of the License, or 1.11 +(at your option) any later version. 1.12 + 1.13 +This program is distributed in the hope that it will be useful, 1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 +GNU Lesser General Public License for more details. 1.17 + 1.18 +You should have received a copy of the GNU Lesser General Public License 1.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 1.20 +*/ 1.21 +#include "config.h" 1.22 +#include <stdio.h> 1.23 +#include <vector> 1.24 +#include <string> 1.25 +#include <map> 1.26 +#include <algorithm> 1.27 +#include "theme.h" 1.28 +#include "widget.h" 1.29 + 1.30 +#ifdef WIN32 1.31 +#include <windows.h> 1.32 + 1.33 +static void *dlopen(const char *name, int flags); 1.34 +static void dlclose(void *so); 1.35 +static void *dlsym(void *so, const char *symbol); 1.36 +#else 1.37 +#include <unistd.h> 1.38 +#include <dlfcn.h> 1.39 +#endif 1.40 + 1.41 +#ifdef HAVE_OPENGL_H 1.42 +#include "opengl.h" 1.43 + 1.44 +#else 1.45 + 1.46 +#ifdef __APPLE__ 1.47 +#include <OpenGL/gl.h> 1.48 +#else 1.49 +#include <GL/gl.h> 1.50 +#endif 1.51 + 1.52 +#endif /* HAVE_OPENGL_H_ */ 1.53 + 1.54 +#ifndef PREFIX 1.55 +#define PREFIX "/usr/local" 1.56 +#endif 1.57 + 1.58 +namespace goatkit { 1.59 + 1.60 +struct ThemeImpl { 1.61 + void *so; 1.62 + WidgetDrawFunc (*lookup_theme_draw_func)(const char*); 1.63 + mutable std::map<std::string, WidgetDrawFunc> func_cache; 1.64 +}; 1.65 + 1.66 +Theme *theme; 1.67 +static std::vector<std::string> search_paths; 1.68 +static const char *fallback_paths[] = { 1.69 + PREFIX "/share/goatkit", 1.70 + 0 1.71 +}; 1.72 + 1.73 +void add_theme_path(const char *path) 1.74 +{ 1.75 + if(!path || !*path) return; 1.76 + 1.77 + std::string s = path; 1.78 + int last = s.length() - 1; 1.79 + if(s[last] == '/' || s[last] == '\\') { 1.80 + s.erase(last); 1.81 + } 1.82 + 1.83 + if(std::find(search_paths.begin(), search_paths.end(), s) != search_paths.end()) { 1.84 + return; 1.85 + } 1.86 + 1.87 + search_paths.push_back(s); 1.88 +} 1.89 + 1.90 +Theme::Theme() 1.91 +{ 1.92 + impl = new ThemeImpl; 1.93 + impl->so = 0; 1.94 + impl->lookup_theme_draw_func = 0; 1.95 +} 1.96 + 1.97 +Theme::~Theme() 1.98 +{ 1.99 + unload(); 1.100 + delete impl; 1.101 +} 1.102 + 1.103 +typedef WidgetDrawFunc (*LookupFunc)(const char*); 1.104 + 1.105 +bool Theme::load(const char *name) 1.106 +{ 1.107 + unload(); 1.108 + 1.109 + std::string fname = std::string(name) + ".gtheme"; 1.110 + if(!(impl->so = dlopen(fname.c_str(), RTLD_LAZY))) { 1.111 + for(size_t i=0; i<search_paths.size(); i++) { 1.112 + std::string path = search_paths[i] + "/" + fname; 1.113 + 1.114 + if((impl->so = dlopen(path.c_str(), RTLD_LAZY))) { 1.115 + break; 1.116 + } 1.117 + } 1.118 + 1.119 + // try the fallback paths 1.120 + if(!impl->so) { 1.121 + for(int i=0; fallback_paths[i]; i++) { 1.122 + std::string path = std::string(fallback_paths[i]) + "/" + fname; 1.123 + 1.124 + if((impl->so = dlopen(path.c_str(), RTLD_LAZY))) { 1.125 + break; 1.126 + } 1.127 + } 1.128 + } 1.129 + 1.130 + if(!impl->so) { 1.131 + fprintf(stderr, "%s: failed to load theme plugin: %s\n", __func__, name); 1.132 + return false; 1.133 + } 1.134 + } 1.135 + 1.136 + // loaded the shared object, now get the lookup function 1.137 + impl->lookup_theme_draw_func = (LookupFunc)dlsym(impl->so, "get_widget_func"); 1.138 + if(!impl->lookup_theme_draw_func) { 1.139 + fprintf(stderr, "%s: invalid theme plugin %s\n", __func__, name); 1.140 + unload(); 1.141 + return false; 1.142 + } 1.143 + 1.144 + return true; 1.145 +} 1.146 + 1.147 +void Theme::unload() 1.148 +{ 1.149 + if(impl->so) { 1.150 + dlclose(impl->so); 1.151 + impl->so = 0; 1.152 + } 1.153 + impl->func_cache.clear(); 1.154 +} 1.155 + 1.156 +WidgetDrawFunc Theme::get_draw_func(const char *type) const 1.157 +{ 1.158 + std::map<std::string, WidgetDrawFunc>::const_iterator it = impl->func_cache.find(type); 1.159 + if(it == impl->func_cache.end()) { 1.160 + // don't have it cached, try to look it up 1.161 + WidgetDrawFunc func; 1.162 + if(impl->lookup_theme_draw_func && (func = impl->lookup_theme_draw_func(type))) { 1.163 + impl->func_cache[type] = func; 1.164 + return func; 1.165 + } 1.166 + 1.167 + // can't look it up, return the default 1.168 + return default_draw_func; 1.169 + } 1.170 + return it->second; 1.171 +} 1.172 + 1.173 +#define LERP(a, b, t) ((a) + ((b) - (a)) * t) 1.174 +#define DEF_TEX_SZ 32 1.175 +void default_draw_func(const Widget *w) 1.176 +{ 1.177 + static unsigned int tex; 1.178 + 1.179 + if(!tex) { 1.180 + unsigned char *pixels = new unsigned char[DEF_TEX_SZ * DEF_TEX_SZ * 3]; 1.181 + unsigned char *ptr = pixels; 1.182 + for(int i=0; i<DEF_TEX_SZ; i++) { 1.183 + for(int j=0; j<DEF_TEX_SZ; j++) { 1.184 + bool stripe = (((j + i) / 8) & 1) == 1; 1.185 + ptr[0] = ptr[1] = ptr[2] = stripe ? 255 : 0; 1.186 + ptr += 3; 1.187 + } 1.188 + } 1.189 + 1.190 + glGenTextures(1, &tex); 1.191 + glBindTexture(GL_TEXTURE_2D, tex); 1.192 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1.193 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.194 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, DEF_TEX_SZ, DEF_TEX_SZ, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); 1.195 + delete [] pixels; 1.196 + } 1.197 + 1.198 + Vec2 pos = w->get_position(); 1.199 + Vec2 sz = w->get_size(); 1.200 + float aspect = sz.x / sz.y; 1.201 + 1.202 +#if !defined(GL_ES_VERSION_2_0) 1.203 + glPushAttrib(GL_ENABLE_BIT); 1.204 + glEnable(GL_TEXTURE_2D); 1.205 +#endif 1.206 + glBindTexture(GL_TEXTURE_2D, tex); 1.207 + 1.208 + float offs = w->get_pressed() * 0.1 * sz.y; 1.209 + glMatrixMode(GL_MODELVIEW); 1.210 + glPushMatrix(); 1.211 + glTranslatef(offs, -offs, 0); 1.212 + 1.213 + float active = w->get_active(); 1.214 + float hover = w->get_under_mouse(); 1.215 + 1.216 + float rg = LERP(0.4, 1.0, hover); 1.217 + float b = LERP(rg, 0, active); 1.218 + glColor3f(rg, rg, b); 1.219 + 1.220 + glBegin(GL_QUADS); 1.221 + glTexCoord2f(0, 1); 1.222 + glVertex2f(pos.x, pos.y); 1.223 + glTexCoord2f(aspect, 1); 1.224 + glVertex2f(pos.x + sz.x, pos.y); 1.225 + glTexCoord2f(aspect, 0); 1.226 + glVertex2f(pos.x + sz.x, pos.y + sz.y); 1.227 + glTexCoord2f(0, 0); 1.228 + glVertex2f(pos.x, pos.y + sz.y); 1.229 + glEnd(); 1.230 + 1.231 + glPopMatrix(); 1.232 + 1.233 +#ifndef GL_ES_VERSION_2_0 1.234 + glPopAttrib(); 1.235 +#endif 1.236 +} 1.237 + 1.238 +} // namespace goatkit 1.239 + 1.240 +#ifdef WIN32 1.241 +// XXX untested 1.242 +static void *dlopen(const char *name, int flags) 1.243 +{ 1.244 + return LoadLibrary(name); 1.245 +} 1.246 + 1.247 +static void dlclose(void *so) 1.248 +{ 1.249 + FreeLibrary(so); 1.250 +} 1.251 + 1.252 +static void *dlsym(void *so, const char *symbol) 1.253 +{ 1.254 + return (void*)GetProcAddress(so, symbol); 1.255 +} 1.256 +#endif