pingus-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Pingus-CVS] r3861 - in trunk: . fontgen


From: grumbel at BerliOS
Subject: [Pingus-CVS] r3861 - in trunk: . fontgen
Date: Fri, 18 Jul 2008 00:53:42 +0200

Author: grumbel
Date: 2008-07-18 00:53:41 +0200 (Fri, 18 Jul 2008)
New Revision: 3861

Added:
   trunk/fontgen/
   trunk/fontgen/README
   trunk/fontgen/SConstruct
   trunk/fontgen/bitmap.cpp
   trunk/fontgen/bitmap.hpp
   trunk/fontgen/fontgen.cpp
Log:
Added utility to generate bitmap fonts from TTF


Property changes on: trunk/fontgen
___________________________________________________________________
Name: svn:ignore
   + fontgen
.sconsign.dblite


Added: trunk/fontgen/README
===================================================================
--- trunk/fontgen/README        2008-07-17 21:50:15 UTC (rev 3860)
+++ trunk/fontgen/README        2008-07-17 22:53:41 UTC (rev 3861)
@@ -0,0 +1,8 @@
+FontGen
+=======
+
+A simple utility application that takes a TTF file and converts it
+into a .pgm along with a text file describing which character maps to
+which coordinates.
+
+# EOF #

Added: trunk/fontgen/SConstruct
===================================================================
--- trunk/fontgen/SConstruct    2008-07-17 21:50:15 UTC (rev 3860)
+++ trunk/fontgen/SConstruct    2008-07-17 22:53:41 UTC (rev 3861)
@@ -0,0 +1,7 @@
+env = Environment()
+env.ParseConfig('freetype-config --libs --cflags')
+env['CXXFLAGS'] += ['-g', '-O0', '-Wall']
+env['LIBS']     += ['jpeg']
+env.Program('fontgen', ['fontgen.cpp', 'bitmap.cpp'])
+
+# EOF #

Added: trunk/fontgen/bitmap.cpp
===================================================================
--- trunk/fontgen/bitmap.cpp    2008-07-17 21:50:15 UTC (rev 3860)
+++ trunk/fontgen/bitmap.cpp    2008-07-17 22:53:41 UTC (rev 3861)
@@ -0,0 +1,180 @@
+/*  $Id$
+**   __      __ __             ___        __   __ __   __
+**  /  \    /  \__| ____    __| _/_______/  |_|__|  | |  |   ____
+**  \   \/\/   /  |/    \  / __ |/  ___/\   __\  |  | |  | _/ __ \
+**   \        /|  |   |  \/ /_/ |\___ \  |  | |  |  |_|  |_\  ___/
+**    \__/\  / |__|___|  /\____ /____  > |__| |__|____/____/\___  >
+**         \/          \/      \/    \/                         \/
+**  Copyright (C) 2005 Ingo Ruhnke <address@hidden>
+**
+**  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., 59 Temple Place - Suite 330, Boston, MA
+**  02111-1307, USA.
+*/
+
+#include <stdio.h>
+#include <jpeglib.h>
+#include <iostream>
+#include <algorithm>
+#include <fstream>
+#include <string.h>
+#include "bitmap.hpp"
+
+Bitmap::Bitmap(int width_, int height_)
+  : width(width_),
+    height(height_),
+    buffer(new unsigned char[width * height])
+{
+  memset(buffer, 255, width * height);
+}
+
+Bitmap::~Bitmap()
+{
+  delete[] buffer;
+}
+
+void
+Bitmap::clear()
+{
+  memset(buffer, 255, width * height);
+}
+
+void
+Bitmap::blit(const Bitmap& source, int x_pos, int y_pos)
+{
+  int start_x = std::max(0, -x_pos);
+  int start_y = std::max(0, -y_pos);
+  
+  int end_x = std::min(source.width,  width  - x_pos);
+  int end_y = std::min(source.height, height - y_pos);
+ 
+  for(int y = start_y; y < end_y; ++y)
+    for(int x = start_x; x < end_x; ++x)
+      { // opaque blit, could use alpha/add blit instead
+        buffer[(y + y_pos) * width + (x + x_pos)] = source.buffer[y * 
source.width + x];
+      }
+}
+
+void 
+Bitmap::write_pgm(const std::string& filename)
+{
+  std::ofstream out(filename.c_str());
+  
+  out << "P2" << std::endl;
+  out << "# txt2png" << std::endl;
+  out << get_width() << " " << get_height() << std::endl;
+  out << "255" << std::endl;
+  for(int y = 0; y < get_height(); ++y)
+    for(int x = 0; x < get_width(); ++x)
+      {
+        out << int(at(x, y)) << " ";
+      }
+  out << std::endl;
+}
+
+void
+Bitmap::write_jpg(const std::string& filename)
+{
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  
+  /* More stuff */
+  FILE * outfile;              /* target file */
+
+  cinfo.err = jpeg_std_error(&jerr);
+  /* Now we can initialize the JPEG compression object. */
+  jpeg_create_compress(&cinfo);
+
+  if ((outfile = fopen(filename.c_str(), "wb")) == NULL)
+    {
+      std::cerr << "can't open "  << filename << std::endl;
+      return;
+    }
+  jpeg_stdio_dest(&cinfo, outfile);
+
+  cinfo.image_width  = get_width();
+  cinfo.image_height = get_height();
+  cinfo.input_components = 1;  //3     /* # of color components per pixel */
+  cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
+
+  jpeg_set_defaults(&cinfo);
+
+  jpeg_set_quality(&cinfo, 85, TRUE /* limit to baseline-JPEG values */);
+
+  /* TRUE ensures that we will write a complete interchange-JPEG file.
+   * Pass TRUE unless you are very sure of what you're doing. */
+  jpeg_start_compress(&cinfo, TRUE);
+
+  JSAMPROW row_pointer[get_height()];  /* pointer to JSAMPLE row[s] */
+
+  for(int y = 0; y < get_height(); ++y)
+    row_pointer[y] = &buffer[y * get_width()];
+
+  while (cinfo.next_scanline < cinfo.image_height) 
+    {
+      jpeg_write_scanlines(&cinfo, row_pointer, get_height());
+    }
+
+  jpeg_finish_compress(&cinfo);
+
+  fclose(outfile);
+
+  jpeg_destroy_compress(&cinfo);
+}
+
+unsigned char
+Bitmap::at(int x, int y)
+{
+  return buffer[y * width + x];
+}
+
+void
+Bitmap::invert(int x1, int y1, int x2, int y2)
+{
+  x1 = std::max(0, x1);
+  y1 = std::max(0, y1);
+
+  x2 = std::min(width,  x2);
+  y2 = std::min(height, y2);
+
+  for(int y = y1; y < y2; ++y)
+    for(int x = x1; x < x2; ++x)
+      {
+        buffer[y * width + x] = 255 - buffer[y * width + x];
+      }
+}
+
+void
+Bitmap::fill(int x1, int y1, int x2, int y2, unsigned char c)
+{  
+  x1 = std::max(0, x1);
+  y1 = std::max(0, y1);
+
+  x2 = std::min(width,  x2);
+  y2 = std::min(height, y2);
+
+  for(int y = y1; y < y2; ++y)
+    for(int x = x1; x < x2; ++x)
+      {
+        buffer[y * width + x] = c;
+      }
+}
+
+void
+Bitmap::truncate_height(int height_)
+{
+  height = height_;
+}
+
+/* EOF */


Property changes on: trunk/fontgen/bitmap.cpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/fontgen/bitmap.hpp
===================================================================
--- trunk/fontgen/bitmap.hpp    2008-07-17 21:50:15 UTC (rev 3860)
+++ trunk/fontgen/bitmap.hpp    2008-07-17 22:53:41 UTC (rev 3861)
@@ -0,0 +1,66 @@
+/*  $Id$
+**   __      __ __             ___        __   __ __   __
+**  /  \    /  \__| ____    __| _/_______/  |_|__|  | |  |   ____
+**  \   \/\/   /  |/    \  / __ |/  ___/\   __\  |  | |  | _/ __ \
+**   \        /|  |   |  \/ /_/ |\___ \  |  | |  |  |_|  |_\  ___/
+**    \__/\  / |__|___|  /\____ /____  > |__| |__|____/____/\___  >
+**         \/          \/      \/    \/                         \/
+**  Copyright (C) 2005 Ingo Ruhnke <address@hidden>
+**
+**  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., 59 Temple Place - Suite 330, Boston, MA
+**  02111-1307, USA.
+*/
+
+#ifndef HEADER_BITMAP_HPP
+#define HEADER_BITMAP_HPP
+
+/** */
+class Bitmap
+{
+private:
+  int width;
+  int height;
+  unsigned char* buffer;
+
+public:
+  Bitmap(int width, int height);
+  ~Bitmap();
+
+  int get_width() { return width; }
+  int get_height() { return height; }
+
+  unsigned char at(int x, int y);
+
+  void blit(const Bitmap& source, int x, int y);
+  unsigned char* get_data() { return buffer; }
+  void clear();
+  void write_pgm(const std::string& filename);
+  void write_jpg(const std::string& filename);
+
+  void truncate_height(int height);
+
+  /** Invert the given region */
+  void invert(int x1, int y1, int x2, int y2);
+
+  /** Fill the given region with color \a c */
+  void fill(int x1, int y1, int x2, int y2, unsigned char c);
+private:
+  Bitmap (const Bitmap&);
+  Bitmap& operator= (const Bitmap&);
+};
+
+#endif
+
+/* EOF */


Property changes on: trunk/fontgen/bitmap.hpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: trunk/fontgen/fontgen.cpp
===================================================================
--- trunk/fontgen/fontgen.cpp   2008-07-17 21:50:15 UTC (rev 3860)
+++ trunk/fontgen/fontgen.cpp   2008-07-17 22:53:41 UTC (rev 3861)
@@ -0,0 +1,143 @@
+#include <stdlib.h>
+#include <string>
+#include <stdexcept>
+#include <vector>
+#include <iostream>
+#include <fstream>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+
+#include "bitmap.hpp"
+
+FT_Library library;
+
+void generate_font(const std::string& filename, int px_size, int border, int 
img_width,
+                   std::ostream& image_stream, 
+                   std::ostream& metadata_stream)
+{
+  // Read the TTF font file content into buffer
+  std::ifstream fin(filename.c_str());
+  std::istreambuf_iterator<char> first(fin), last;
+  std::vector<char> buffer(first, last); 
+
+  FT_Face face;
+  if (FT_New_Memory_Face(library, 
+                         reinterpret_cast<FT_Byte*>(&*buffer.begin()), 
buffer.size(), 
+                         0, &face))
+    {
+      throw std::runtime_error("Couldn't load font: '" + filename + "'");
+    }
+      
+  FT_Set_Pixel_Sizes(face, px_size, px_size);
+  FT_Select_Charmap(face,  FT_ENCODING_UNICODE);
+
+
+  std::cout << "BBox: " << px_size << " "
+            << px_size * face->bbox.xMin/face->units_per_EM << " " 
+            << px_size * face->bbox.yMin/face->units_per_EM << " " 
+            << px_size * face->bbox.xMax/face->units_per_EM << " " 
+            << px_size * face->bbox.yMax/face->units_per_EM << " " 
+            << face->units_per_EM
+            << std::endl;
+
+  Bitmap image_bitmap(img_width, 4096);
+
+  // We limit ourself to 256 characters for the momemnt
+  int x_pos = 0;
+  int y_pos = 0;
+
+  //for(int glyph_index = 0; glyph_index < 256; glyph_index += 1)
+
+  FT_ULong  charcode;                                              
+  FT_UInt   glyph_index;                                                
+  
+  charcode = FT_Get_First_Char( face, &glyph_index );
+  while ( glyph_index != 0 )                                            
+    {                                                                          
                            
+      if (FT_Load_Char( face,  glyph_index, FT_LOAD_RENDER))//| 
FT_LOAD_FORCE_AUTOHINT))
+        {
+          std::cerr << "couldn't load char: " << glyph_index << " '" << 
char(glyph_index) << "'" << std::endl;
+          //impl->characters.push_back(0);
+        }
+      else
+        {
+          FT_GlyphSlot glyph = face->glyph;;
+
+          //int x_offset =  glyph->bitmap_left;
+          //int y_offset = -glyph->bitmap_top;
+          //int advance = (glyph->advance.x >> 6);
+          
+          Bitmap glyph_bitmap(glyph->bitmap.width, glyph->bitmap.rows);
+
+          for(int y = 0; y < glyph_bitmap.get_height(); ++y)
+            for(int x = 0; x < glyph_bitmap.get_width(); ++x)
+              {
+                glyph_bitmap.get_data()[y * glyph_bitmap.get_width() + x] = 
255 - glyph->bitmap.buffer[y * glyph->bitmap.pitch + x];
+              }
+
+          if (x_pos + glyph_bitmap.get_width() + 2*border > 
image_bitmap.get_width())
+            {
+              x_pos = border;
+              y_pos += px_size + 2*border;
+
+              image_bitmap.blit(glyph_bitmap, x_pos+border, y_pos+border);
+              x_pos += glyph_bitmap.get_width() + 2*border;
+            }
+          else
+            {
+              image_bitmap.blit(glyph_bitmap, x_pos+border, y_pos+border);
+              x_pos += glyph_bitmap.get_width() + 2*border;
+            }
+        }
+
+      charcode = FT_Get_Next_Char( face, charcode, &glyph_index );
+    }
+
+  image_bitmap.truncate_height(y_pos + px_size + border);
+  image_bitmap.write_pgm("/tmp/out.pgm");
+
+  FT_Done_Face(face);
+}
+  
+int main(int argc, char** argv)
+{
+  if (argc != 5)
+    {
+      std::cout << "Usage: " << argv[0] << " TTFFILE SIZE BORDER WIDTH" << 
std::endl;
+      return EXIT_FAILURE;
+    }
+
+  std::string ttf_filename = argv[1];
+  int  pixel_size   = atoi(argv[2]);
+  int  border       = atoi(argv[3]);
+  int  image_width  = atoi(argv[4]);
+
+  std::ofstream metadata_stream("/tmp/output.font");
+  std::ofstream image_stream("/tmp/output.pgm");
+
+  std::cout << "Generating image from " << ttf_filename << " with size " << 
pixel_size << " and width " << image_width << std::endl;
+
+  try 
+    {
+      FT_Error   error;
+  
+      error = FT_Init_FreeType(&library);
+      if (error)
+        throw std::runtime_error("could not initialize FreeType");   
+        
+      generate_font(ttf_filename, pixel_size, border, image_width, 
+                    image_stream, metadata_stream);
+        
+      FT_Done_FreeType(library);
+    } 
+  catch(std::exception& err)
+    {
+      std::cout << "Error: " << err.what() << std::endl;
+    }
+
+  return 0;
+}
+  
+/* EOF */


Property changes on: trunk/fontgen/fontgen.cpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native





reply via email to

[Prev in Thread] Current Thread [Next in Thread]