Panagiotis Christopoulos Charitos пре 14 година
родитељ
комит
4ed784ebb7
6 измењених фајлова са 347 додато и 9 уклоњено
  1. 0 0
      build/debug/Makefile
  2. 7 0
      src/Main.cpp
  3. 62 7
      src/Ui/UiFont.cpp
  4. 9 2
      src/Ui/UiFont.h
  5. 202 0
      src/Ui/UiFtFontLoader.cpp
  6. 67 0
      src/Ui/UiFtFontLoader.h

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
build/debug/Makefile


+ 7 - 0
src/Main.cpp

@@ -40,6 +40,7 @@
 #include "Skin.h"
 #include "MaterialRuntime.h"
 #include "Globals.h"
+#include "UiFtFontLoader.h"
 
 
 // map (hard coded)
@@ -431,6 +432,12 @@ void mainLoop()
 //======================================================================================================================
 int main(int argc, char* argv[])
 {
+	FT_Vector s = {100, 100};
+	Ui::FtFontLoader fnt("/users/panoscc/src/godlike-projects/libfreetype/Ruritania-Outline.ttf", s);
+	fnt.saveImage("/tmp/test.tga");
+
+	return 0;
+
 	try
 	{
 		AppSingleton::getInstance().init(argc, argv);

+ 62 - 7
src/Ui/UiFont.cpp

@@ -10,7 +10,10 @@
 #include "Assert.h"
 
 
-struct Glyph
+namespace Ui {
+
+
+struct FtGlyph
 {
 	FT_Glyph glyph;
 	FT_Glyph_Metrics metrics;
@@ -24,7 +27,7 @@ inline FT_Int toPixels(FT_Int a)
 
 
 /// Get 127 glyphs from a face
-static void getGlyphs(FT_Face& face, Vec<Glyph>& glyphs)
+static void getGlyphs(FT_Face& face, Vec<FtGlyph>& glyphs)
 {
 	const uint MAX_GLYPHS = 127;
 	ASSERT(glyphs.size() == 0);
@@ -70,12 +73,12 @@ static void copyBitmap(const unsigned char* srcImg, const FT_Vector& srcSize, co
 
 
 /// Compute the size of the image with all the glyphs
-static void computeImageSize(const Vec<Glyph>& glyphs, FT_Vector& size)
+static void computeImageSize(const Vec<FtGlyph>& glyphs, FT_Vector& size)
 {
 	size.x = 0;
 	size.y = 0;
 
-	BOOST_FOREACH(const Glyph& glyph, glyphs)
+	BOOST_FOREACH(const FtGlyph& glyph, glyphs)
 	{
 		// Inc the width
 		size.x += toPixels(glyph.metrics.width);
@@ -91,7 +94,7 @@ static void computeImageSize(const Vec<Glyph>& glyphs, FT_Vector& size)
 
 /// Given a filename and a font size create an image with all the glyphs
 static void createImage(const char* filename, const FT_Vector& fontSize,
-                        Vec<Glyph>& glyphs, Vec<uchar>& img, FT_Vector& imgSize)
+                        Vec<FtGlyph>& glyphs, Vec<uchar>& img, FT_Vector& imgSize)
 {
 	FT_Library library;
 	FT_Face face;
@@ -119,7 +122,7 @@ static void createImage(const char* filename, const FT_Vector& fontSize,
 
 	// Draw all glyphs to the image
 	FT_Vector pos = {0, 0};
-	BOOST_FOREACH(Glyph& glyph, glyphs)
+	BOOST_FOREACH(FtGlyph& glyph, glyphs)
 	{
 		FT_Glyph_To_Bitmap(&glyph.glyph, FT_RENDER_MODE_NORMAL, 0, 0);
 		FT_BitmapGlyph bit = (FT_BitmapGlyph) glyph.glyph;
@@ -132,7 +135,7 @@ static void createImage(const char* filename, const FT_Vector& fontSize,
 	}
 
 	// Clean
-	BOOST_FOREACH(Glyph& glyph, glyphs)
+	BOOST_FOREACH(FtGlyph& glyph, glyphs)
 	{
 		FT_Done_Glyph(glyph.glyph);
 	}
@@ -142,3 +145,55 @@ static void createImage(const char* filename, const FT_Vector& fontSize,
 
 	//save_image(image, imgSize.x, imgSize.y);
 }
+
+
+/// Save image to TGA. For debuging purposes
+static void saveImage(const char* filename, const Vec<uchar>& buff, int w, int h)
+{
+	char tgaHeader[12] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+	FILE* fp = fopen(filename, "wb");
+
+	fwrite(tgaHeader, 1, sizeof(tgaHeader), fp);
+
+	unsigned char header6[6];
+
+	header6[0] = w % 256;
+	header6[1] = w / 256;
+	header6[2] = h % 256;
+	header6[3] = h / 256;
+	header6[4] = 24;
+	header6[5] = 0;
+
+	fwrite(header6, 1, sizeof(header6), fp);
+
+	for(int i = h - 1; i > -1; i--)
+	{
+		for(int j = 0; j < w; j++)
+		{
+			fwrite(&buff[i * w + j], 1, sizeof(unsigned char), fp);
+			fwrite(&buff[i * w + j], 1, sizeof(unsigned char), fp);
+			fwrite(&buff[i * w + j], 1, sizeof(unsigned char), fp);
+		}
+	}
+
+	fclose(fp);
+}
+
+
+//======================================================================================================================
+// create                                                                                                              =
+//======================================================================================================================
+void Font::create(const char* fontFilename, uint nominalWidth, uint NominalHeight)
+{
+	Vec<FtGlyph> glyphs;
+	Vec<uchar> img;
+	FT_Vector imgSize;
+	FT_Vector fontSize = {nominalWidth, NominalHeight};
+	createImage(fontFilename, fontSize, glyphs, img, imgSize);
+
+	saveImage("/tmp/test.tga", img, imgSize.x, imgSize.y);
+}
+
+
+} // end namespace

+ 9 - 2
src/Ui/UiFont.h

@@ -17,7 +17,8 @@ namespace Ui {
 class Font
 {
 	public:
-		Font(const char* fontFilename, uint nominalWidth, uint NominalHeight);
+		/// Constructor
+		Font(const char* fontFilename, uint nominalWidth, uint nominalHeight);
 
 	private:
 		struct Glyph
@@ -31,10 +32,16 @@ class Font
 		std::auto_ptr<Texture> map; ///< The texture map that contains all the glyphs
 		boost::ptr_vector<Glyph> glyphs; ///< A set of glyphs from ' ' to ' ' + 128
 
-
+		void create(const char* fontFilename, uint nominalWidth, uint NominalHeight);
 };
 
 
+inline Font::Font(const char* fontFilename, uint nominalWidth, uint nominalHeight)
+{
+	create(fontFilename, nominalWidth, nominalHeight);
+}
+
+
 } // end namespace
 
 

+ 202 - 0
src/Ui/UiFtFontLoader.cpp

@@ -0,0 +1,202 @@
+#include <boost/foreach.hpp>
+#include "UiFtFontLoader.h"
+#include "Exception.h"
+
+
+namespace Ui {
+
+
+//======================================================================================================================
+// getGlyphs                                                                                                           =
+//======================================================================================================================
+void FtFontLoader::getGlyphs()
+{
+	glyphs.resize(GLYPHS_NUM);
+
+	for(uint n = 1; n < GLYPHS_NUM; n++)
+	{
+		char c = ' ' + n;
+
+		FT_UInt glyphIndex = FT_Get_Char_Index(face, c);
+
+		FT_Error error = FT_Load_Glyph(face, glyphIndex, FT_LOAD_DEFAULT);
+		if(error)
+		{
+			throw EXCEPTION("FT_Load_Glyph failed");
+		}
+
+		glyphs[n].metrics = face->glyph->metrics;
+
+		error = FT_Get_Glyph(face->glyph, &glyphs[n].glyph);
+		if(error)
+		{
+			throw EXCEPTION("FT_Get_Glyph failed");
+		}
+	}
+
+	glyphs[0].metrics.width = glyphs['_' - ' '].metrics.width;
+}
+
+
+//======================================================================================================================
+// copyBitmap                                                                                                          =
+//======================================================================================================================
+void FtFontLoader::copyBitmap(const uchar* srcImg, const FT_Vector& srcSize, const FT_Vector& pos)
+{
+	for(int i = 0; i < srcSize.y; i++)
+	{
+		for(int j = 0; j < srcSize.x; j++)
+		{
+			int jj = j + pos.x;
+			int ii = i + pos.y;
+			img[ii * imgSize.x + jj] = srcImg[i * srcSize.x + j];
+		}
+	}
+}
+
+
+//======================================================================================================================
+// computeImageSize                                                                                                    =
+//======================================================================================================================
+void FtFontLoader::computeImageSize()
+{
+	imgSize.x = 0;
+	imgSize.y = 0;
+
+	//
+	// Get img height
+	//
+	BOOST_FOREACH(const Glyph& glyph, glyphs)
+	{
+		if(toPixels(glyph.metrics.height) > imgSize.y)
+		{
+			imgSize.y = toPixels(glyph.metrics.height);
+		}
+	}
+
+	imgSize.y = GLYPHS_NUM / GLYPHS_PER_ROW * imgSize.y;
+
+	//
+	// Get img width
+	//
+
+
+	// For all rows
+	for(uint i = 0; i < GLYPHS_NUM / GLYPHS_PER_ROW; i++)
+	{
+		uint rowSize = 0;
+		// For all columns
+		for(uint j = 0; j < GLYPHS_PER_ROW; j++)
+		{
+			rowSize += toPixels(glyphs[i * GLYPHS_PER_ROW + j].metrics.width);
+		}
+
+		if(rowSize > imgSize.x)
+		{
+			imgSize.x = rowSize;
+		}
+	}
+}
+
+
+
+//======================================================================================================================
+// createImage                                                                                                         =
+//======================================================================================================================
+void FtFontLoader::createImage(const char* filename, const FT_Vector& fontSize)
+{
+	FT_Library library;
+	FT_Face face;
+	FT_Error error;
+
+	// Create lib
+	error = FT_Init_FreeType(&library);
+	if(error)
+	{
+		throw EXCEPTION("FT_Init_FreeType failed");
+	}
+
+	// Create face and set glyph size
+	error = FT_New_Face(library, filename, 0, &face);
+	FT_Set_Pixel_Sizes(face, fontSize.x, fontSize.y);
+
+	// Get all glyphs
+	getGlyphs();
+
+	// Get final image size and create image buffer
+	computeImageSize();
+
+	size_t size = imgSize.x * imgSize.y * 2 * sizeof(uchar);
+	img.resize(size, 128);
+
+	// Draw all glyphs to the image
+	FT_Vector pos = {0, 0};
+	// For all rows
+	for(uint i = 0; i < GLYPHS_NUM / GLYPHS_PER_ROW; i++)
+	{
+		// For all columns
+		for(uint j = 0; j < GLYPHS_PER_ROW; j++)
+		{
+			Glyph& glyph = glyphs[i * GLYPHS_PER_ROW + j];
+
+			FT_Glyph_To_Bitmap(&glyph.glyph, FT_RENDER_MODE_NORMAL, 0, 0);
+			FT_BitmapGlyph bit = (FT_BitmapGlyph) glyph.glyph;
+
+			FT_Vector srcSize = {toPixels(glyph.metrics.width), toPixels(glyph.metrics.height)};
+
+			copyBitmap(bit->bitmap.buffer, srcSize, pos);
+
+			pos.x += toPixels(glyph.metrics.width);
+		}
+
+		pos.y += imgSize.y / (GLYPHS_NUM / GLYPHS_PER_ROW);
+	}
+
+	// Clean
+	BOOST_FOREACH(Glyph& glyph, glyphs)
+	{
+		FT_Done_Glyph(glyph.glyph);
+	}
+
+	FT_Done_Face(face);
+	FT_Done_FreeType(library);
+}
+
+
+//======================================================================================================================
+// saveImage                                                                                                           =
+//======================================================================================================================
+void FtFontLoader::saveImage(const char* filename) const
+{
+	char tgaHeader[12] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+	FILE* fp = fopen(filename, "wb");
+
+	fwrite(tgaHeader, 1, sizeof(tgaHeader), fp);
+
+	uchar header6[6];
+
+	header6[0] = imgSize.x % 256;
+	header6[1] = imgSize.x / 256;
+	header6[2] = imgSize.y % 256;
+	header6[3] = imgSize.y / 256;
+	header6[4] = 24;
+	header6[5] = 0;
+
+	fwrite(header6, 1, sizeof(header6), fp);
+
+	for(int i = imgSize.y - 1; i > -1; i--)
+	{
+		for(int j = 0; j < imgSize.x; j++)
+		{
+			fwrite(&img[i * imgSize.x + j], 1, sizeof(uchar), fp);
+			fwrite(&img[i * imgSize.x + j], 1, sizeof(uchar), fp);
+			fwrite(&img[i * imgSize.x + j], 1, sizeof(uchar), fp);
+		}
+	}
+
+	fclose(fp);
+}
+
+
+} // end namespace

+ 67 - 0
src/Ui/UiFtFontLoader.h

@@ -0,0 +1,67 @@
+#ifndef UI_FT_FONT_LOADER_H
+#define UI_FT_FONT_LOADER_H
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+#include "Vec.h"
+#include "StdTypes.h"
+
+
+namespace Ui {
+
+
+/// A helper class that uses libfreetype to load glyphs from a font file and gather the metrics for each glyhp
+class FtFontLoader
+{
+	public:
+		static const uint GLYPHS_NUM = 128;
+		static const uint GLYPHS_PER_ROW = 16;
+
+		FtFontLoader(const char* filename, const FT_Vector& fontSize);
+
+		/// Save the image (img) to TGA. Its for debugging purposes
+		void saveImage(const char* filename) const;
+
+	private:
+		struct Glyph
+		{
+			FT_Glyph glyph;
+			FT_Glyph_Metrics metrics;
+		};
+
+		/// @name Data
+		/// @{
+		FT_Library library;
+		FT_Face face;
+		Vec<Glyph> glyphs;
+		Vec<uchar> img;
+		FT_Vector imgSize;
+		/// @}
+
+		FT_Int toPixels(FT_Int a) {return a >> 6;}
+
+		/// Reads the face and extracts the glyphs
+		void getGlyphs();
+
+		/// Copy one bitmap to img
+		void copyBitmap(const uchar* srcImg, const FT_Vector& srcSize, const FT_Vector& pos);
+
+		/// Compute image size (imgSize) using the glyphs set
+		void computeImageSize();
+
+		/// Given a filename and a font size create an image with all the glyphs
+		void createImage(const char* filename, const FT_Vector& fontSize);
+};
+
+
+inline FtFontLoader::FtFontLoader(const char* filename, const FT_Vector& fontSize)
+{
+	createImage(filename, fontSize);
+}
+
+
+} // end namespace
+
+
+#endif

Неке датотеке нису приказане због велике количине промена