Support a variable-length list of fallback fonts (and support Arial MS Unicode) inste...
authorSteinar H. Gunderson <sesse@samfundet.no>
Sat, 19 Feb 2005 13:54:10 +0000 (13:54 +0000)
committerSteinar H. Gunderson <sesse@samfundet.no>
Sat, 19 Feb 2005 13:54:10 +0000 (13:54 +0000)
bigscreen/Makefile
bigscreen/ccbs_bigscreen.cpp
bigscreen/glwindow.cpp [deleted file]
bigscreen/glwindow.h [deleted file]

index 24584ac..e3cd02c 100644 (file)
@@ -3,8 +3,8 @@ CXX=g++
 CPPFLAGS=-I/usr/include/postgresql $(shell freetype-config --cflags) -Itinyptc/
 CXXFLAGS=-g -Wall
 LDFLAGS=-L/usr/X11R6/lib
-LIBS=-lGL -lX11 -lXext -lXxf86vm $(shell freetype-config --libs) $(shell libpq3-config) -lpqxx tinyptc/libtinyptc.a
-CCBS_BIGSCREEN_OBJS=ccbs_bigscreen.o glwindow.o
+LIBS=$(shell freetype-config --libs) $(shell libpq3-config) -lpqxx tinyptc/libtinyptc.a -lX11
+CCBS_BIGSCREEN_OBJS=ccbs_bigscreen.o
 
 all: ccbs-bigscreen
 
index 78dc4a3..9d173b2 100644 (file)
@@ -50,7 +50,7 @@ void pqxx::from_string<widestring>(const char *from, widestring &to)
        to = from;
 }
 
-int my_draw_text(const widestring &str, unsigned char *buf, int xpos, int ypos, bool real_render, int r, int g, int b, FT_Face face, FT_Face symbolface);
+int my_draw_text(const widestring &str, unsigned char *buf, int xpos, int ypos, bool real_render, int r, int g, int b, std::vector<FT_Face> &fontlist);
 
 class Tournament {
 public:
@@ -59,7 +59,7 @@ public:
 };
 
 Tournament active_tournament;
-FT_Face font, symbolfont;
+std::vector<FT_Face> fonts;
 
 /* A trigger that sets a flag whenever it's trigged. */
 class FlagTrigger : pqxx::trigger {
@@ -140,7 +140,7 @@ void main_loop(pqxx::connection &conn)
        pqxx::result res( t.exec("SELECT * FROM songs WHERE title LIKE 'M%'") );
        unsigned y = 0;
        for (pqxx::result::const_iterator i = res.begin(); i != res.end(); ++i) {
-               my_draw_text(i["title"].as(widestring()), framebuf, 0, y, 1, 255, 255, 255, font, symbolfont);
+               my_draw_text(i["title"].as(widestring()), framebuf, 0, y, 1, 255, 255, 255, fonts);
                y += 20;
 //             std::fprintf(stderr, "%s\n", i["title"].c_str());
        }
@@ -153,41 +153,56 @@ void main_loop(pqxx::connection &conn)
 void init_freetype()
 {
        FT_Library library;
+       FT_Face face;
        if (FT_Init_FreeType(&library))
                throw std::runtime_error("FreeType init failed.");
-       if (FT_New_Face(library, "/usr/share/fonts/truetype/msttcorefonts/Georgia.ttf", 0, &font))
-               throw std::runtime_error("Face opening failed.");
-       if (FT_New_Face(library, "/usr/share/fonts/truetype/freefont/FreeSerif.ttf", 0, &symbolfont))
+
+       // Georgia
+       if (FT_New_Face(library, "/usr/share/fonts/truetype/msttcorefonts/Georgia.ttf", 0, &face))
                throw std::runtime_error("Face opening failed.");
-       if (FT_Set_Char_Size(font, 0, 12 * 64, 96, 96))
-               throw std::runtime_error("Size set failed.");
-       if (FT_Set_Char_Size(symbolfont, 0, 12 * 64, 96, 96))
+       if (FT_Set_Char_Size(face, 0, 12 * 64, 96, 96))
                throw std::runtime_error("Size set failed.");
+       fonts.push_back(face);
+
+       // 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 {
+               if (FT_Set_Char_Size(face, 0, 12 * 64, 96, 96))
+                       throw std::runtime_error("Size set failed.");
+               fonts.push_back(face);
+       }
+       
+       // FreeSerif
+       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 {
+               if (FT_Set_Char_Size(face, 0, 12 * 64, 96, 96))
+                       throw std::runtime_error("Size set failed.");
+               fonts.push_back(face);
+       }
 }
 
-int my_draw_text(const widestring &str, unsigned char *buf, int xpos, int ypos, bool real_render, int r, int g, int b, FT_Face face, FT_Face symbolface)
+int my_draw_text(const widestring &str, unsigned char *buf, int xpos, int ypos, bool real_render, int r, int g, int b, std::vector<FT_Face> &fontlist)
 {
        FT_GlyphSlot slot;
        int x = 0;
 
        for (widestring::const_iterator i = str.begin(); i != str.end(); ++i) {
-               // try the normal font first, fall back if there's some special character
-               int glyph_index = FT_Get_Char_Index(face, *i);
-               if (glyph_index == 0) {
-                       std::fprintf(stderr, "Couldn't find U+%x in primary face, falling back to symbol face\n",
-                               *i);
-                       glyph_index = FT_Get_Char_Index(symbolface, *i);
-                       if (glyph_index == 0) {
-                               std::fprintf(stderr, "Couldn't find U+%x in symbol face, ignoring\n", *i);
+               int glyph_index;
+               for (std::vector<FT_Face>::const_iterator j = fontlist.begin(); j != fontlist.end(); ++j) {
+                       glyph_index = FT_Get_Char_Index(*j, *i);
+                       if (glyph_index == 0)
                                continue;
-                       }
-                       if (FT_Load_Glyph(symbolface, glyph_index, FT_LOAD_RENDER))
-                               throw std::runtime_error("Couldn't load glyph from symbol face");
-                       slot = symbolface->glyph;
-               } else {
-                       if (FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER))
-                               throw std::runtime_error("Couldn't load glyph from primary face");
-                       slot = face->glyph;
+
+                       if (FT_Load_Glyph(*j, glyph_index, FT_LOAD_RENDER))
+                               throw std::runtime_error("Couldn't load glyph");
+                       slot = (*j)->glyph;
+                       break;
+               }
+               if (glyph_index == 0) {
+                       std::fprintf(stderr, "Warning: Could not find a glyph in any font for U+%x, ignoring\n", *i);
+                       continue;
                }
 
                if (real_render) {
diff --git a/bigscreen/glwindow.cpp b/bigscreen/glwindow.cpp
deleted file mode 100644 (file)
index 45d46b5..0000000
+++ /dev/null
@@ -1,425 +0,0 @@
-#include <stdio.h>
-
-#ifdef WIN32
-#include <windows.h>
-#endif
-
-#ifdef __linux__
-#include <unistd.h>
-#include <GL/glx.h>
-#include <X11/extensions/xf86vmode.h>
-#include <X11/keysym.h>
-#endif
-
-#include <GL/gl.h>
-#include <GL/glu.h>
-
-#include "glwindow.h"
-
-#ifdef WIN32
-LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
-
-/* this is ugly, but so is Win32 ;-) */
-GLWindow *win;
-#endif
-
-#define DEMOLIB_XASPECT 4.0f
-#define DEMOLIB_YASPECT 3.0f
-
-void GLWindow::resize(int x, int y, int w, int h)
-{
-       /* Prevent division by zero */
-       if (h == 0) {
-               h = 1;
-       }
-
-       float aspect = (float)w / (float)h;
-       if (aspect > DEMOLIB_XASPECT / DEMOLIB_YASPECT) {
-               int new_w = (int)((float)h * DEMOLIB_XASPECT / DEMOLIB_YASPECT);
-               x += (w - new_w) / 2;
-               w = new_w;
-       } else if (aspect < DEMOLIB_XASPECT / DEMOLIB_YASPECT) {
-               int new_h = (int)((float)w * DEMOLIB_YASPECT / DEMOLIB_XASPECT);
-               y += (h - new_h) / 2;
-               h = new_h;
-       }
-       glViewport(x, y, w, h);
-
-#ifdef __linux__
-//     XClearWindow(this->dpy, this->win);
-#endif
-}
-
-GLWindow::GLWindow(char *title, int width, int height, int bpp, bool fullscreen, int zbuffer, int visual_id)
-{
-#ifdef WIN32
-       GLuint PixelFormat;
-       WNDCLASS wc;
-       DWORD dwExStyle;
-       DWORD dwStyle;
-       DEVMODE dmScreenSettings;
-
-       if (visual_id != -1) {
-               EnumDisplaySettings(NULL, visual_id, &dmScreenSettings);
-               width = dmScreenSettings.dmPelsWidth;
-               height = dmScreenSettings.dmPelsHeight;
-               bpp = dmScreenSettings.dmBitsPerPel;
-       } else {
-               memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
-               dmScreenSettings.dmSize = sizeof(dmScreenSettings);
-               dmScreenSettings.dmPelsWidth = width;
-               dmScreenSettings.dmPelsHeight = height;
-               dmScreenSettings.dmBitsPerPel = bpp;
-               dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
-       }
-       win = this;
-       
-       RECT WindowRect;
-       WindowRect.left = (long)0;
-       WindowRect.right = (long)width;
-       WindowRect.top = (long)0;
-       WindowRect.bottom = (long)height;
-       
-#endif /* WIN32 */     
-#ifdef __linux__
-       XVisualInfo *vi;
-       int dpyWidth = 0, dpyHeight = 0;
-       int i;
-       XF86VidModeModeInfo **modes;
-       int modeNum;
-       int bestMode;
-       Atom wmDelete;
-       Window winDummy;
-       unsigned int borderDummy;
-
-       static int attrList[] = {
-               GLX_RGBA, 
-               GLX_RED_SIZE, 1,
-               GLX_GREEN_SIZE, 1,
-               GLX_BLUE_SIZE, 1,
-               GLX_DOUBLEBUFFER,
-               GLX_DEPTH_SIZE, zbuffer,
-               GLX_STENCIL_SIZE, 4,
-               None
-       };
-#endif /* __linux__ */
-
-       this->x = 0;
-       this->y = 0;
-       this->width = width;
-       this->height = height;
-       this->bpp = bpp;
-       this->fullscreen = fullscreen;
-       this->zbuffer = zbuffer;
-       this->done = 0;
-       
-#ifdef WIN32
-       this->hInstance = GetModuleHandle(NULL);
-       wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
-       wc.lpfnWndProc = WndProc;
-       wc.cbClsExtra = 0;
-       wc.cbWndExtra = 0;
-       wc.hInstance = this->hInstance;
-       wc.hIcon = NULL;
-       wc.hCursor = NULL;
-       wc.hbrBackground = NULL;
-       wc.lpszMenuName = NULL;
-       wc.lpszClassName = "Excess-OGL";
-
-       if( !RegisterClass(&wc) ) throw "Couldn't register Window Class";
-
-#endif /* WIN32 */
-#ifdef __linux__
-       /* set best mode to current */
-       bestMode = 0;
-
-       /* get a connection */
-       this->dpy = XOpenDisplay(0);
-       this->screen = DefaultScreen(this->dpy);
-
-       if (fullscreen) {
-               XF86VidModeGetAllModeLines(this->dpy, this->screen, &modeNum, &modes);
-
-               /* save desktop-resolution before switching modes */
-               this->deskMode = *modes[0];
-
-               /* look for mode with requested resolution */
-               for (i = 0; i < modeNum; i++) {
-                       if ((modes[i]->hdisplay == width) && (modes[i]->vdisplay == height)) {
-                               bestMode = i;
-                       }
-               }
-
-               /* if we don't have it, bomb out */
-               if (bestMode == 0 && (modes[0]->hdisplay != width || modes[0]->vdisplay != height)) {
-                       throw "Couldn't set requested screen mode.";
-               }
-       }
-
-       if (visual_id != -1) {
-               XVisualInfo tmplate;
-               int nret;
-               
-               tmplate.visualid = visual_id;
-               vi = XGetVisualInfo(this->dpy, VisualIDMask, &tmplate, &nret);
-               if (vi == NULL) {
-                       throw "Couldn't get selected visual!";
-               }
-       } else {
-               /* get an appropriate visual */
-               vi = glXChooseVisual(this->dpy, this->screen, attrList);
-               if (vi == NULL) {
-                       throw "Couldn't get double-buffered visual";
-               }
-       }
-
-       /* create a GLX context */
-       this->ctx = glXCreateContext(this->dpy, vi, NULL, GL_TRUE);
-
-       /* create a color map (umm, needed?) */
-       Colormap cmap = XCreateColormap(this->dpy, RootWindow(this->dpy, vi->screen),
-               vi->visual, AllocNone);
-       this->attr.colormap = cmap;
-
-       /* make a blank cursor */
-       {
-               static char data[1] = {0};
-               Cursor cursor;
-               Pixmap blank;
-               XColor dummy;
-
-               blank = XCreateBitmapFromData(this->dpy, RootWindow(this->dpy, vi->screen), data, 1, 1);
-               if (blank == None)
-                       throw "Out of memory!";
-               cursor = XCreatePixmapCursor(this->dpy, blank, blank, &dummy, &dummy, 0, 0);
-               XFreePixmap(this->dpy, blank);
-               this->attr.cursor = cursor;
-       }
-               
-       this->attr.border_pixel = 0;
-#endif /* __linux__ */
-
-       /* change screen mode */        
-       if (fullscreen) {
-#ifdef WIN32
-               if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
-                       throw "Couldn't set requested screen mode.";
-               }
-#endif /* WIN32 */
-#ifdef __linux__
-               XF86VidModeSwitchToMode(this->dpy, this->screen, modes[bestMode]);
-               XF86VidModeSetViewPort(this->dpy, this->screen, 0, 0);
-               dpyWidth = modes[bestMode]->hdisplay;
-               dpyHeight = modes[bestMode]->vdisplay;
-               XFree(modes);
-#endif /* __linux__ */
-       }
-
-       /* create the window */
-#ifdef WIN32
-       if (fullscreen) {
-               dwExStyle = WS_EX_APPWINDOW;
-               dwStyle = WS_POPUP;
-               ShowCursor(FALSE);
-       } else {
-               dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
-               dwStyle = WS_OVERLAPPEDWINDOW;
-       }
-
-       AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
-
-       if (!(hWnd = CreateWindowEx(dwExStyle,
-                                   "Excess-OGL",
-                                   title,
-                                   dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
-                                   0, 0,
-                                   WindowRect.right - WindowRect.left,
-                                   WindowRect.bottom - WindowRect.top,
-                                   NULL,
-                                   NULL,
-                                   this->hInstance,
-                                   NULL))) {
-               delete this;
-               throw "Could not change screenmode";
-       }
-#endif
-#ifdef __linux__
-       this->attr.background_pixel = 0;
-
-       if (fullscreen) {
-               /* create a fullscreen window */
-               this->attr.override_redirect = True;
-               this->attr.event_mask = KeyPressMask | ButtonPressMask |
-                                       StructureNotifyMask;
-
-               this->win = XCreateWindow(this->dpy, RootWindow(this->dpy, vi->screen),
-                       0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual,
-                       CWColormap | CWCursor | CWEventMask | CWOverrideRedirect,
-                       &this->attr);
-               XWarpPointer(this->dpy, None, this->win, 0, 0, 0, 0, 0, 0);
-               XMapRaised(this->dpy, this->win);
-               XGrabKeyboard(this->dpy, this->win, True, GrabModeAsync,
-                       GrabModeAsync, CurrentTime);
-               XGrabPointer(this->dpy, this->win, True, ButtonPressMask,
-                       GrabModeAsync, GrabModeAsync, this->win, None, CurrentTime);
-       } else {
-               /* create a window in window mode*/
-               this->attr.event_mask = KeyPressMask | ButtonPressMask |
-                       StructureNotifyMask;
-               this->win = XCreateWindow(this->dpy, RootWindow(this->dpy, vi->screen),
-                       0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
-                       CWColormap | CWBorderPixel | CWEventMask, &this->attr);
-
-               /* only set window title and handle wm_delete_events if in windowed mode */
-               wmDelete = XInternAtom(this->dpy, "WM_DELETE_WINDOW", True);
-               XSetWMProtocols(this->dpy, this->win, &wmDelete, 1);
-               XSetStandardProperties(this->dpy, this->win, title,
-                       title, None, NULL, 0, NULL);
-               XMapRaised(this->dpy, this->win);
-       }
-#endif /* __linux__ */
-
-#ifdef WIN32
-       static PIXELFORMATDESCRIPTOR pfd = {
-               sizeof(PIXELFORMATDESCRIPTOR),
-               1,
-               PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
-               PFD_TYPE_RGBA,
-               bpp,
-               0, 0, 0, 0, 0, 0,
-               0,
-               0,
-               0,
-               0, 0, 0, 0,
-               zbuffer,
-               8,
-               0,
-               PFD_MAIN_PLANE,
-               0,
-               0, 0, 0
-       };
-       
-       hDC = GetDC(hWnd);
-       PixelFormat = ChoosePixelFormat(hDC, &pfd);
-       if (PixelFormat == 0) {
-               throw "Could not find a usable pixelformat";
-       }
-       SetPixelFormat(hDC, PixelFormat, &pfd);
-       hRC = wglCreateContext(hDC);
-       wglMakeCurrent(hDC, hRC);
-       ShowWindow(hWnd, SW_SHOW);
-       SetForegroundWindow(hWnd);
-       SetFocus(hWnd);
-
-       SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
-#endif /* WIN32        */
-#ifdef __linux__
-       /* connect the glx-context to the window */
-       glXMakeCurrent(this->dpy, this->win, this->ctx);
-       XClearWindow(this->dpy, this->win);
-       XGetGeometry(this->dpy, this->win, &winDummy, &this->x, &this->y,
-               &this->width, &this->height, &borderDummy, &this->bpp);
-       if (!glXIsDirect(this->dpy, this->ctx)) {
-               throw "No direct rendering (hardware acceleration) available!";
-       }
-
-       nice(-7);
-#endif /* __linux__ */
-
-       this->resize(0, 0, this->width, this->height);
-}
-
-GLWindow::~GLWindow()
-{
-#ifdef __linux__
-       if (this->ctx) {
-               if (!glXMakeCurrent(this->dpy, None, NULL)) {
-                       throw "Could not release drawing context.";
-               }
-               glXDestroyContext(this->dpy, this->ctx);
-               this->ctx = NULL;
-       }
-#endif
-
-       if (fullscreen) {
-#ifdef __linux__
-               XF86VidModeSwitchToMode(this->dpy, this->screen, &this->deskMode);
-               XF86VidModeSetViewPort(this->dpy, this->screen, 0, 0);
-#endif
-#ifdef WIN32
-               ChangeDisplaySettings(NULL,0);
-               ShowCursor(TRUE);
-#endif
-       }
-
-#ifdef __linux__
-       XCloseDisplay(this->dpy);
-#endif
-
-#ifdef WIN32
-       if (hRC) {
-               wglMakeCurrent(NULL, NULL);
-               wglDeleteContext(hRC);
-               hRC = NULL;
-       }
-       
-       if (hDC != NULL && ReleaseDC(hWnd, hDC)) hDC = NULL;
-       if (hWnd != NULL && DestroyWindow(hWnd)) hWnd = NULL;
-       UnregisterClass("Excess-OGL", hInstance);
-#endif
-}
-
-void GLWindow::flip()
-{
-#ifdef WIN32
-       MSG msg;
-       if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
-               if (msg.message == WM_QUIT) {
-                       this->done = TRUE;
-               } else {
-                       TranslateMessage(&msg);
-                       DispatchMessage(&msg);
-               }
-       }
-       SwapBuffers(this->hDC);
-#endif
-#ifdef __linux__
-       glXSwapBuffers(this->dpy, this->win);
-#endif
-}
-
-bool GLWindow::is_done()
-{
-       return this->done;
-}
-
-#ifdef WIN32
-LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-       switch (uMsg) {
-       case WM_SYSCOMMAND:
-               switch (wParam) {
-               case SC_SCREENSAVE:
-               case SC_MONITORPOWER:
-                       return 0;
-               }
-               break;
-
-       case WM_CLOSE:
-               PostQuitMessage(0);
-               return 0;
-
-       case WM_KEYUP:
-               if (wParam == VK_ESCAPE)
-                       PostQuitMessage(0);
-               return 0;
-
-       case WM_SIZE:
-               win->resize(0, 0, LOWORD(lParam), HIWORD(lParam));
-               return 0;
-       }
-
-       return DefWindowProc(hWnd, uMsg, wParam, lParam);
-}
-#endif //WIN32
diff --git a/bigscreen/glwindow.h b/bigscreen/glwindow.h
deleted file mode 100644 (file)
index a2a8e32..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _GLWINDOW_H
-#define _GLWINDOW_H
-
-#ifdef WIN32
-#include <windows.h>
-#endif
-
-#ifdef __linux__
-#include <GL/glx.h>
-#include <X11/extensions/xf86vmode.h>
-#include <X11/keysym.h>
-#endif
-
-#include <GL/gl.h>
-#include <GL/glu.h>
-
-class GLWindow {
-public:
-       GLWindow(char *title, int width, int height, int bpp, bool fullscreen, int zbuffer, int visual_id);
-       ~GLWindow();
-       void resize(int x, int y, int w, int h);
-       void flip();
-       bool is_done();
-
-       friend class DemoHandler;
-       friend class DirectSoundAudioDriver;
-       
-protected:
-#ifdef WIN32
-       HDC hDC;
-       HGLRC hRC;
-       HWND hWnd;
-       HINSTANCE hInstance;
-#endif
-#ifdef __linux__
-       Display *dpy;
-       int screen;
-       Window win;
-       GLXContext ctx;
-       XSetWindowAttributes attr;
-       Bool fs;
-       XF86VidModeModeInfo deskMode;
-#endif                                             
-       
-       char *title;
-       bool fullscreen;
-       int x, y;
-       unsigned int width, height;
-       unsigned int bpp;
-       int zbuffer;
-       bool done;
-       void initGL();
-};
-
-#endif