Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Examples

# font.cc

Simple bitmap font rendering example.

    // -*- C++ -*-
    /*
     * font.cc:
     * Simple bitmap font rendering example.
     *
     * written by Naofumi Yasufuku  <naofumi@users.sourceforge.net>
     */

    #include <iostream>
    #include <cstdlib>

    #include <gtkmm.h>

    #include <gtkglmm.h>

    #ifdef G_OS_WIN32
    #define WIN32_LEAN_AND_MEAN 1
    #include <windows.h>
    #endif

    #include <GL/gl.h>
    #include <GL/glu.h>

    //
    // OpenGL frame buffer configuration utilities.
    //

    struct GLConfigUtil
    {
      static void print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig,
                                  const char* attrib_str,
                                  int attrib,
                                  bool is_boolean);

      static void examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig);
    };

    //
    // Print a configuration attribute.
    //
    void GLConfigUtil::print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig,
                                       const char* attrib_str,
                                       int attrib,
                                       bool is_boolean)
    {
      int value;

      if (glconfig->get_attrib(attrib, value))
        {
          std::cout << attrib_str << " = ";
          if (is_boolean)
            std::cout << (value == true ? "true" : "false") << std::endl;
          else
            std::cout << value << std::endl;
        }
      else
        {
          std::cout << "*** Cannot get "
                    << attrib_str
                    << " attribute value\n";
        }
    }

    //
    // Print configuration attributes.
    //
    void GLConfigUtil::examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig)
    {
      std::cout << "\nOpenGL visual configurations :\n\n";

      std::cout << "glconfig->is_rgba() = "
                << (glconfig->is_rgba() ? "true" : "false")
                << std::endl;
      std::cout << "glconfig->is_double_buffered() = "
                << (glconfig->is_double_buffered() ? "true" : "false")
                << std::endl;
      std::cout << "glconfig->is_stereo() = "
                << (glconfig->is_stereo() ? "true" : "false")
                << std::endl;
      std::cout << "glconfig->has_alpha() = "
                << (glconfig->has_alpha() ? "true" : "false")
                << std::endl;
      std::cout << "glconfig->has_depth_buffer() = "
                << (glconfig->has_depth_buffer() ? "true" : "false")
                << std::endl;
      std::cout << "glconfig->has_stencil_buffer() = "
                << (glconfig->has_stencil_buffer() ? "true" : "false")
                << std::endl;
      std::cout << "glconfig->has_accum_buffer() = "
                << (glconfig->has_accum_buffer() ? "true" : "false")
                << std::endl;

      std::cout << std::endl;

      print_gl_attrib(glconfig, "Gdk::GL::USE_GL",           Gdk::GL::USE_GL,           true);
      print_gl_attrib(glconfig, "Gdk::GL::BUFFER_SIZE",      Gdk::GL::BUFFER_SIZE,      false);
      print_gl_attrib(glconfig, "Gdk::GL::LEVEL",            Gdk::GL::LEVEL,            false);
      print_gl_attrib(glconfig, "Gdk::GL::RGBA",             Gdk::GL::RGBA,             true);
      print_gl_attrib(glconfig, "Gdk::GL::DOUBLEBUFFER",     Gdk::GL::DOUBLEBUFFER,     true);
      print_gl_attrib(glconfig, "Gdk::GL::STEREO",           Gdk::GL::STEREO,           true);
      print_gl_attrib(glconfig, "Gdk::GL::AUX_BUFFERS",      Gdk::GL::AUX_BUFFERS,      false);
      print_gl_attrib(glconfig, "Gdk::GL::RED_SIZE",         Gdk::GL::RED_SIZE,         false);
      print_gl_attrib(glconfig, "Gdk::GL::GREEN_SIZE",       Gdk::GL::GREEN_SIZE,       false);
      print_gl_attrib(glconfig, "Gdk::GL::BLUE_SIZE",        Gdk::GL::BLUE_SIZE,        false);
      print_gl_attrib(glconfig, "Gdk::GL::ALPHA_SIZE",       Gdk::GL::ALPHA_SIZE,       false);
      print_gl_attrib(glconfig, "Gdk::GL::DEPTH_SIZE",       Gdk::GL::DEPTH_SIZE,       false);
      print_gl_attrib(glconfig, "Gdk::GL::STENCIL_SIZE",     Gdk::GL::STENCIL_SIZE,     false);
      print_gl_attrib(glconfig, "Gdk::GL::ACCUM_RED_SIZE",   Gdk::GL::ACCUM_RED_SIZE,   false);
      print_gl_attrib(glconfig, "Gdk::GL::ACCUM_GREEN_SIZE", Gdk::GL::ACCUM_GREEN_SIZE, false);
      print_gl_attrib(glconfig, "Gdk::GL::ACCUM_BLUE_SIZE",  Gdk::GL::ACCUM_BLUE_SIZE,  false);
      print_gl_attrib(glconfig, "Gdk::GL::ACCUM_ALPHA_SIZE", Gdk::GL::ACCUM_ALPHA_SIZE, false);

      std::cout << std::endl;
    }

    //
    // Simple OpenGL scene using bitmap font.
    //

    class FontGLScene : public Gtk::DrawingArea,
                        public Gtk::GL::Widget<FontGLScene>
    {
    public:
      FontGLScene();
      virtual ~FontGLScene();

    protected:
      virtual void on_realize();
      virtual bool on_configure_event(GdkEventConfigure* event);
      virtual bool on_expose_event(GdkEventExpose* event);

    protected:
      // font rendering stuff:
      static const Glib::ustring m_FontString;
      GLuint m_FontListBase;
      int m_FontHeight;
    };

    const Glib::ustring FontGLScene::m_FontString = "courier 12";

    FontGLScene::FontGLScene()
      : m_FontListBase(0), m_FontHeight(0)
    {
      //
      // Configure OpenGL-capable visual.
      //

      Glib::RefPtr<Gdk::GL::Config> glconfig;

      // Try double-buffered visual
      glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB    |
                                         Gdk::GL::MODE_DEPTH  |
                                         Gdk::GL::MODE_DOUBLE);
      if (!glconfig)
        {
          std::cerr << "*** Cannot find the double-buffered visual.\n"
                    << "*** Trying single-buffered visual.\n";

          // Try single-buffered visual
          glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB   |
                                             Gdk::GL::MODE_DEPTH);
          if (!glconfig)
            {
              std::cerr << "*** Cannot find any OpenGL-capable visual.\n";
              std::exit(1);
            }
        }

      // print frame buffer attributes.
      GLConfigUtil::examine_gl_attrib(glconfig);

      //
      // Set OpenGL-capability to the widget.
      //

      set_gl_capability(glconfig);
    }

    FontGLScene::~FontGLScene()
    {
    }

    void FontGLScene::on_realize()
    {
      // We need to call the base on_realize()
      Gtk::DrawingArea::on_realize();

      //
      // Get GL::Window.
      //

      Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();

      //
      // GL calls.
      //

      // *** OpenGL BEGIN ***
      if (!glwindow->gl_begin(get_gl_context()))
        return;

      //
      // Generate font display lists.
      //

      m_FontListBase = glGenLists (128);

      Pango::FontDescription font_desc(m_FontString);

      Glib::RefPtr<Pango::Font> font =
        Gdk::GL::Font::use_pango_font(font_desc, 0, 128, m_FontListBase);
      if (!font)
        {
          std::cerr << "*** Can't load font "
                    << m_FontString
                    << std::endl;
          Gtk::Main::quit();
        }

      Pango::FontMetrics font_metrics = font->get_metrics();

      m_FontHeight = font_metrics.get_ascent() + font_metrics.get_descent();
      m_FontHeight = PANGO_PIXELS(m_FontHeight);

      glClearColor(1.0, 1.0, 1.0, 1.0);
      glClearDepth(1.0);

      glViewport(0, 0, get_width(), get_height());

      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(0.0, get_width(),
              0.0, get_height(),
              -1.0, 1.0);

      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();

      glwindow->gl_end();
      // *** OpenGL END ***
    }

    bool FontGLScene::on_configure_event(GdkEventConfigure* event)
    {
      //
      // Get GL::Window.
      //

      Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();

      //
      // GL calls.
      //

      // *** OpenGL BEGIN ***
      if (!glwindow->gl_begin(get_gl_context()))
        return false;

      glViewport(0, 0, get_width(), get_height());

      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(0.0, get_width(),
              0.0, get_height(),
              -1.0, 1.0);

      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();

      glwindow->gl_end();
      // *** OpenGL END ***

      return true;
    }

    bool FontGLScene::on_expose_event(GdkEventExpose* event)
    {
      //
      // Get GL::Window.
      //

      Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();

      //
      // GL calls.
      //

      // *** OpenGL BEGIN ***
      if (!glwindow->gl_begin(get_gl_context()))
        return false;

      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      //
      // Draw some text.
      //
      glColor3f(0.0, 0.0, 0.0);
      for (int i = 2; i >= -2; --i)
        {
          glRasterPos2f(10.0, 0.5*get_height() + i*m_FontHeight);
          for (int j = ' '; j <= 'Z'; ++j)
            glCallList(m_FontListBase+j);
        }

      //
      // Show font description string.
      //
      glColor3f(1.0, 0.0, 0.0);
      glRasterPos2f(10.0, 10.0);
      glListBase(m_FontListBase);
      glCallLists(m_FontString.length(), GL_UNSIGNED_BYTE, m_FontString.c_str());

      // Swap buffers.
      if (glwindow->is_double_buffered())
        glwindow->swap_buffers();
      else
        glFlush();

      glwindow->gl_end();
      // *** OpenGL END ***

      return true;
    }

    //
    // The application class.
    //

    class Font : public Gtk::Window
    {
    public:
      Font();
      virtual ~Font();

    protected:
      // signal handlers:
      void on_button_quit_clicked();

    protected:
      // member widgets:
      Gtk::VBox m_VBox;
      FontGLScene m_FontGLScene;
      Gtk::Button m_ButtonQuit;

    };

    Font::Font()
      : m_VBox(false, 0), m_ButtonQuit("Quit")
    {
      //
      // Top-level window.
      //

      set_title("Font");

      // Get automatically redrawn if any of their children changed allocation.
      set_reallocate_redraws(true);

      add(m_VBox);

      //
      // Simple OpenGL scene using bitmap font.
      //

      m_FontGLScene.set_size_request(640, 240);

      m_VBox.pack_start(m_FontGLScene);

      //
      // Simple quit button.
      //

      m_ButtonQuit.signal_clicked().connect(
        sigc::mem_fun(*this, &Font::on_button_quit_clicked));

      m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0);

      //
      // Show window.
      //

      show_all();
    }

    Font::~Font()
    {}

    void Font::on_button_quit_clicked()
    {
      Gtk::Main::quit();
    }

    //
    // Main.
    //

    int main(int argc, char** argv)
    {
      Gtk::Main kit(argc, argv);

      //
      // Init gtkglextmm.
      //

      Gtk::GL::init(argc, argv);

      //
      // Query OpenGL extension version.
      //

      int major, minor;
      Gdk::GL::query_version(major, minor);
      std::cout << "OpenGL extension version - "
                << major << "." << minor << std::endl;

      //
      // Instantiate and run the application.
      //

      Font font;

      kit.run(font);

      return 0;
    }