]> git.sesse.net Git - ccbs/blobdiff - bigscreen/fonts.cpp
Move the theming out to a runtime-read config file. Opens, among others, for differen...
[ccbs] / bigscreen / fonts.cpp
index 86910a6b2757a4c27974274eecc2b874fde95eb4..0381157c687097dfe59642deb976b301b23c42a5 100644 (file)
@@ -1,35 +1,61 @@
 #include <cstdio>
 #include <vector>
 #include <stdexcept>
+#include <map>
+#include <string>
 #include "fonts.h"
 #include "resolution.h"
+#include "theme.h"
 
-std::vector<FT_Face> fonts;
+extern std::map<std::string, std::string> config;
+std::map<std::string, FT_Face> faces;
+
+std::vector<std::string> split(const std::string &str, char delim)
+{
+       std::vector<std::string> ret;
+       std::string s;
+       for (unsigned i = 0; i < str.size(); ++i) {
+               if (str[i] == delim) {
+                       ret.push_back(s);
+                       s.clear();
+               } else {
+                       s.push_back(str[i]);
+               }
+       }
+       if (!s.empty()) {
+               ret.push_back(s);
+       }
+       return ret;
+}
 
 void init_freetype()
 {
        FT_Library library;
-       FT_Face face;
        if (FT_Init_FreeType(&library))
                throw std::runtime_error("FreeType init failed.");
 
-       // Georgia
-       if (FT_New_Face(library, "/usr/share/fonts/truetype/msttcorefonts/Georgia.ttf", 0, &face))
-               throw std::runtime_error("Face opening failed.");
-       fonts.push_back(face);
+       // Preload all fonts.
+       for (std::map<std::string, std::string>::const_iterator it = config.begin();
+            it != config.end();
+            ++it) {
+               const std::string key = it->first;
+               if (key.size() <= 5 || key.substr(key.size() - 5) != ".font") {
+                       continue;
+               }
 
-       // FreeSerif
-       if (FT_New_Face(library, "/usr/share/fonts/truetype/freefont/FreeSerif.ttf", 0, &face)) {
-               std::fprintf(stderr, "Warning: Couldn't open FreeSerif, some glyphs might not be available\n");
-       } else {
-               fonts.push_back(face);
-       }
-       
-       // Arial Unicode MS
-       if (FT_New_Face(library, "arialuni.ttf", 0, &face)) {
-               std::fprintf(stderr, "Warning: Couldn't open Arial Unicode MS, some glyphs might not be available\n");
-       } else {
-               fonts.push_back(face);
+               std::vector<std::string> font_list = split(it->second, ';');
+               for (unsigned i = 0; i < font_list.size(); ++i) {
+                       if (faces.count(font_list[i])) {
+                               // Already preloaded.
+                               continue;
+                       }
+
+                       FT_Face face;
+                       if (FT_New_Face(library, font_list[i].c_str(), 0, &face)) {
+                               fprintf(stderr, "Warning: Couldn't open '%s', some glyphs might not be available\n", font_list[i].c_str());
+                       }
+                       faces[font_list[i]] = face;
+               }
        }
 }
 
@@ -41,10 +67,23 @@ void set_screen_size(unsigned width, unsigned height)
        screen_height = height;
 }
 
-unsigned my_draw_text(const widestring &str, unsigned char *buf, double size, int xpos, int ypos, int r, int g, int b)
+unsigned my_draw_text(const widestring &str, unsigned char *buf, double size, const std::string &theme_element, int xpos, int ypos)
 {
        FT_GlyphSlot slot;
        int x = 0;
+
+       int r = atoi(get_theme_config(theme_element, "red").c_str());
+       int g = atoi(get_theme_config(theme_element, "green").c_str());
+       int b = atoi(get_theme_config(theme_element, "blue").c_str());
+
+       // Find font faces.
+       std::vector<FT_Face> fonts;
+       std::vector<std::string> font_list = split(get_theme_config(theme_element, "font"), ';');
+       for (unsigned i = 0; i < font_list.size(); ++i) {
+               if (faces.count(font_list[i])) {
+                       fonts.push_back(faces[font_list[i]]);
+               }
+       }
        
        for (std::vector<FT_Face>::const_iterator i = fonts.begin(); i != fonts.end(); ++i) {
                if (FT_Set_Char_Size(*i, 0, unsigned(size * 64.0), 96 * screen_width/LOGICAL_SCREEN_WIDTH, 96 * screen_height/LOGICAL_SCREEN_HEIGHT))
@@ -126,38 +165,30 @@ unsigned my_draw_text(const widestring &str, unsigned char *buf, double size, in
        return x * LOGICAL_SCREEN_WIDTH / screen_width;
 }
 
-void my_draw_text_deferred(std::vector<TextDefer> &td, const widestring &str, double size, int xpos, int ypos, int r, int g, int b, int rn, int gn, int bn)
+void my_draw_text_deferred(std::vector<TextDefer> &td, const widestring &str, double size, const std::string &theme_element, const std::string &fresh_theme_element, int xpos, int ypos)
 {
        TextDefer newtd;
        newtd.str = str;
        newtd.size = size;
        newtd.xpos = xpos;
        newtd.ypos = ypos;
-       newtd.r = r;
-       newtd.g = g;
-       newtd.b = b;
-       newtd.rn = rn;
-       newtd.gn = gn;
-       newtd.bn = bn;
+       newtd.theme_element = theme_element;
+       newtd.fresh_theme_element = fresh_theme_element;
        td.push_back(newtd);
 }
 
 void draw_all_deferred_text(unsigned char *buf, std::vector<TextDefer> &current, std::vector<TextDefer> &old)
 {
        for (unsigned i = 0; i < current.size(); ++i) {
-               int r, g, b;
+               std::string theme_element;
                if (i < old.size() && current[i].str != old[i].str) {
                        // changed text
-                       r = current[i].rn;
-                       g = current[i].gn;
-                       b = current[i].bn;
+                       theme_element = current[i].fresh_theme_element;
                } else {
-                       r = current[i].r;
-                       g = current[i].g;
-                       b = current[i].b;
+                       theme_element = current[i].theme_element;
                }       
                
-               my_draw_text(current[i].str, buf, current[i].size, current[i].xpos, current[i].ypos, r, g, b);
+               my_draw_text(current[i].str, buf, current[i].size, theme_element, current[i].xpos, current[i].ypos);
        }
 }