[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Pingus-CVS] r3861 - in trunk: . fontgen,
grumbel at BerliOS <=