[gens-sdl] OsdFontLoader: New font loader class.
authorDavid Korth <gerbilsoft@gerbilsoft.com>
Sat, 19 Sep 2015 13:37:45 +0000 (09:37 -0400)
committerDavid Korth <gerbilsoft@gerbilsoft.com>
Sat, 19 Sep 2015 13:37:45 +0000 (09:37 -0400)
This class takes a font name and returns an allocated 8-bit image,
along with the width, height, and total size (in bytes) of the image.

OsdGL: Use OsdFontLoader instead of manually accessing the font data.

src/gens-sdl/CMakeLists.txt
src/gens-sdl/Osd/OsdFontLoader.cpp [new file with mode: 0644]
src/gens-sdl/Osd/OsdFontLoader.hpp [new file with mode: 0644]
src/gens-sdl/Osd/OsdGL.cpp

index d3e9338..d8bbb56 100644 (file)
@@ -75,6 +75,7 @@ SET(gens-sdl_OSD_SRCS
        Osd/OsdGL.cpp
        Osd/OsdFont_VGA.cpp
        Osd/OsdFont_C64.cpp
+       Osd/OsdFontLoader.cpp
        )
 
 # OSD headers.
@@ -82,6 +83,7 @@ SET(gens-sdl_OSD_H
        Osd/OsdGL.hpp
        Osd/OsdFont_VGA.hpp
        Osd/OsdFont_C64.hpp
+       Osd/OsdFontLoader.hpp
        )
 
 # Shader sources.
diff --git a/src/gens-sdl/Osd/OsdFontLoader.cpp b/src/gens-sdl/Osd/OsdFontLoader.cpp
new file mode 100644 (file)
index 0000000..74b152c
--- /dev/null
@@ -0,0 +1,101 @@
+/***************************************************************************
+ * gens-sdl: Gens/GS II basic SDL frontend.                                *
+ * OsdFontLoader.hpp: Onscreen Display font loader.                        *
+ *                                                                         *
+ * Copyright (c) 2008-2015 by David Korth.                                 *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU General Public License as published by the   *
+ * Free Software Foundation; either version 2 of the License, or (at your  *
+ * option) any later version.                                              *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of              *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.           *
+ ***************************************************************************/
+
+#include "OsdFontLoader.hpp"
+
+// Fonts.
+// TODO: Add 'name' parameter to OsdFont.
+#include "OsdFont_VGA.hpp"
+#include "OsdFont_C64.hpp"
+
+// C includes.
+#include <stdlib.h>
+
+// C includes. (C++ namespace)
+#include <cstring>
+
+namespace GensSdl {
+
+/**
+ * Load a font as 8-bit grayscale. (GL_ALPHA8, I8)
+ * @param name         [in]  Font name.
+ * @param p_chrW       [out] Character width.
+ * @param p_chrH       [out] Character height.
+ * @param p_sz         [out] Size of allocated data, in bytes.
+ * @return Allocated image data, or nullptr on error.
+ * Caller must free the image data using free().
+ * TODO: This may be switched to aligned_malloc() / aligned_free() later.
+ */
+void *OsdFontLoader::load_A8(const char *name,
+       uint8_t *p_chrW, uint8_t *p_chrH, unsigned int *p_sz)
+{
+       const OsdFont *font;
+       if (!strcmp(name, "VGA")) {
+               font = &VGA_font;
+       } else if (!strcmp(name, "C64")) {
+               font = &C64_font;
+       } else {
+               return nullptr;
+       }
+
+       const uint8_t chrW = font->w;
+       const uint8_t chrH = font->h;
+       const uint8_t *fontData = font->data;
+
+       // Allocate the image buffer.
+       const unsigned int sz = (256 * chrW * chrH);
+       uint8_t *img = (uint8_t*)malloc(sz);
+       if (!img)
+               return nullptr;
+
+       // Converting 1bpp characters to 8bpp.
+       // pitch = 8 bytes per character; 16 per line.
+       const int pitch = chrW * 16;
+       for (int chr = 0; chr < 256; chr++) {
+               const int y_pos = (chr / 16) * chrH;
+               const int x_pos = (chr & 15) * chrW;
+
+               uint8_t *pos = &img[(y_pos * pitch) + x_pos];
+               // TODO: Support chrW != 8.
+               const uint8_t *p_chr_data = &fontData[chr * chrH];
+               for (int y = 0; y < chrH; y++, pos += (pitch - chrW), p_chr_data++) {
+                       uint8_t chr_data = *p_chr_data;
+                       for (int x = chrW; x > 0; x--, chr_data <<= 1) {
+                               *pos = ((chr_data & 0x80) ? 0xFF : 0);
+                               pos++;
+                       }
+               }
+       }
+
+       // Return the data.
+       if (p_chrW) {
+               *p_chrW = chrW;
+       }
+       if (p_chrW) {
+               *p_chrH = chrH;
+       }
+       if (p_sz) {
+               *p_sz = sz;
+       }
+       return img;
+}
+
+}
diff --git a/src/gens-sdl/Osd/OsdFontLoader.hpp b/src/gens-sdl/Osd/OsdFontLoader.hpp
new file mode 100644 (file)
index 0000000..09de2c1
--- /dev/null
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * gens-sdl: Gens/GS II basic SDL frontend.                                *
+ * OsdFontLoader.hpp: Onscreen Display font loader.                        *
+ *                                                                         *
+ * Copyright (c) 2008-2015 by David Korth.                                 *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU General Public License as published by the   *
+ * Free Software Foundation; either version 2 of the License, or (at your  *
+ * option) any later version.                                              *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of              *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.           *
+ ***************************************************************************/
+
+#ifndef __GENS_SDL_OSD_OSDFONTLOADER_HPP__
+#define __GENS_SDL_OSD_OSDFONTLOADER_HPP__
+
+// C includes.
+#include <stdint.h>
+
+namespace GensSdl {
+
+class OsdFontLoader {
+       private:
+               // TODO: Singleton class instead of static class?
+               OsdFontLoader() { };
+               ~OsdFontLoader() { };
+
+       private:
+               // Q_DISABLE_COPY() equivalent.
+               // TODO: Add GensSdl-specific version of Q_DISABLE_COPY().
+               OsdFontLoader(const OsdFontLoader &);
+               OsdFontLoader &operator=(const OsdFontLoader &);
+
+       public:
+               /**
+                * Load a font as 8-bit grayscale. (GL_ALPHA8, I8)
+                * @param name          [in]  Font name.
+                * @param p_chrW        [out] Character width.
+                * @param p_chrH        [out] Character height.
+                * @param p_sz          [out] Size of allocated data, in bytes.
+                * @return Allocated image data, or nullptr on error.
+                * Caller must free the image data using free().
+                * TODO: This may be switched to aligned_malloc() / aligned_free() later.
+                */
+               static void *load_A8(const char *name,
+                       uint8_t *p_chrW, uint8_t *p_chrH, unsigned int *p_sz);
+};
+
+}
+
+#endif /* __GENS_SDL_OSD_OSDFONTLOADER_HPP__ */
index 928189c..ebcf5bf 100644 (file)
@@ -44,9 +44,8 @@ using std::vector;
 // GL Texture wrapper.
 #include "GLTex.hpp"
 
-// OSD fonts.
-#include "OsdFont_VGA.hpp"
-#include "OsdFont_C64.hpp"
+// OSD font loader.
+#include "OsdFontLoader.hpp"
 
 // ZOMG image data.
 #include "libzomg/img_data.h"
@@ -83,8 +82,8 @@ class OsdGLPrivate {
                // Timer.
                LibGens::Timing timer;
 
-               // OSD font.
-               const OsdFont *font;
+               // OSD font properties.
+               uint8_t chrW, chrH;
 
                // OSD queue.
                // NOTE: Manually allocating objects.
@@ -182,7 +181,7 @@ const double OsdGLPrivate::ortho_default[4] = {0.0, 320.0, 240.0, 0.0};
 /** OsdGLPrivate **/
 
 OsdGLPrivate::OsdGLPrivate()
-       : font(&VGA_font)
+       : chrW(0), chrH(0)
        , displayList(0)
        , dirty(true)
        , fpsEnabled(false)
@@ -225,31 +224,15 @@ void OsdGLPrivate::reallocOsdTexture()
                }
        }
 
-       // Create the GL image.
-       // Using GL_ALPHA.
-       // TODO: Optimize this?
-       const uint8_t chrW = font->w;
-       const uint8_t chrH = font->h;
-       const uint8_t *fontData = font->data;
-
-       uint8_t *glImage = (uint8_t*)malloc(256 * chrW * chrH);
-       // Converting 1bpp characters to 8bpp.
-       // pitch = 8 pixels per character; 16 per line.
-       const int pitch = chrW * 16;
-       for (int chr = 0; chr < 256; chr++) {
-               const int y_pos = (chr / 16) * chrH;
-               const int x_pos = (chr & 15) * chrW;
-
-               uint8_t *pos = &glImage[(y_pos * pitch) + x_pos];
-               // TODO: Support chrW != 8.
-               const uint8_t *p_chr_data = &fontData[chr * chrH];
-               for (int y = 0; y < chrH; y++, pos += (pitch - chrW), p_chr_data++) {
-                       uint8_t chr_data = *p_chr_data;
-                       for (int x = chrW; x > 0; x--, chr_data <<= 1) {
-                               *pos = ((chr_data & 0x80) ? 0xFF : 0);
-                               pos++;
-                       }
-               }
+       // Load the OSD font.
+       void *glImage = OsdFontLoader::load_A8("VGA", &chrW, &chrH, nullptr);
+       if (!glImage) {
+               // Error loading the font.
+               // TODO: Show an error message?
+               chrW = 0;
+               chrH = 0;
+               texOsd.dealloc();
+               return;
        }
 
        // Allocate the texture.
@@ -270,10 +253,6 @@ void OsdGLPrivate::reallocOsdTexture()
  */
 void OsdGLPrivate::printLine(int x, int y, const std::string &msg)
 {
-       // TODO: Wordwrapping.
-       const int chrW = font->w;
-       const int chrH = font->h;
-
        // TODO: Precalculate vertices?
        const int len = (int)msg.size();
        // TODO: Allocate once, and reallocate if a larger one is needed?
@@ -288,7 +267,7 @@ void OsdGLPrivate::printLine(int x, int y, const std::string &msg)
                        break;
 
                // Vertex coordinates.
-               GLTex::toCoords(&vtx[i*8], x, y, chrW, chrH);
+               GLTex::toCoords(&vtx[i*8], x, y, (int)chrW, (int)chrH);
                // Texture coordinates.
                memcpy(&txc[i*8], &osdVertex[chr][0], sizeof(osdVertex[chr]));
        }
@@ -668,9 +647,7 @@ void OsdGL::draw(void)
        glBindTexture(GL_TEXTURE_2D, d->texOsd.name);
 
        // TODO: Adjust for visible texture size.
-       const uint8_t chrW = d->font->w;
-       const uint8_t chrH = d->font->h;
-       int y = (240 - chrH);
+       int y = (240 - d->chrH);
 
        // Print from top to bottom to avoid collisions
        // with the drop shadow. (C64 font)
@@ -692,7 +669,7 @@ void OsdGL::draw(void)
                }
 
                // Process this message.
-               y -= chrH;
+               y -= d->chrH;
                firstIdx = i;
        }
 
@@ -718,12 +695,12 @@ void OsdGL::draw(void)
                }
                // TODO: Make the drop shadow optional.
                glColor4f(0.0f, 0.0f, 0.0f, alpha);
-               d->printLine(chrW+1, y+1, osdMsg->msg);
+               d->printLine(d->chrW+1, y+1, osdMsg->msg);
                d->setGLColor(d->msgColor, alpha);
-               d->printLine(chrW, y, osdMsg->msg);
+               d->printLine(d->chrW, y, osdMsg->msg);
 
                // Next line.
-               y += chrH;
+               y += d->chrH;
        }
 
        // Done with vertex and texture coordinate arrays.
@@ -814,7 +791,7 @@ void OsdGL::print(unsigned int duration, const char *msg)
 
        // Number of characters per line.
        // 2 characters margin on the sides.
-       const int line_w = (320 / d->font->w) - 2;
+       const int line_w = (320 / d->chrW) - 2;
 
        // Check for newlines and/or text wrapping.
        // TODO: Actual word wrapping instead of just text wrapping.