Ejemplo n.º 1
0
void CFreeFont::MakeLetter(wchar_t code)
{
	// Первая вещь, которую нам надо сделать, это вывести наш символ
	// в растр. Это делается набором команд FreeType

	// Загрузить глифы для каждого символа.
	if(FT_Load_Glyph(face, FT_Get_Char_Index(face, code), FT_LOAD_DEFAULT))
		throw NOVA_EXP("CFreeFont::MakeLetter - FT_Load_Glyph failed", BAD_OPERATION);

	// Поместить глиф в объект.
	FT_Glyph glyph;
	if(FT_Get_Glyph(face->glyph, &glyph))
		throw NOVA_EXP("CFreeFont::MakeLetter - FT_Get_Glyph failed", BAD_OPERATION);

	// Конвертировать глиф в растр.
	FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
	FT_BitmapGlyph bitmap_glyph = reinterpret_cast<FT_BitmapGlyph>(glyph);

	// С помощью этой ссылки, получаем легкий доступ до растра.
	FT_Bitmap & bitmap = bitmap_glyph->bitmap;

    // Используем нашу вспомогательную функцию для вычисления ширины и высоты
	// текстуры для нашего растра.
	nInt32 bwidth = NextP2(bitmap.width);
	nInt32 bheight = NextP2(bitmap.rows);

	// Выделим память для данных текстуры.
	//nByte * expanded_data = NULL;
	//expanded_data = getmem<nByte>(expanded_data, 2 * bwidth * bheight);
	CMemoryBuffer mem;
	mem.AllocBuffer(2 * bwidth * bheight);
	nByte * expanded_data = (nova::nByte *)mem.GetBegin();

	// Поместим данные в расширенный растр.
	// Отмечу, что использован двухканальный растр (Один для
	// канала яркости и один для альфа), но мы будем назначать
	// обоим каналам одно и тоже значение, которое мы
	// получим из растра FreeType.
	// Мы используем оператор ?: для того чтобы поместить 0 в зону вне растра FreeType.
	for(nInt32 j = 0; j < bheight; ++j)
		for(nInt32 i = 0; i < bwidth; ++i)
			expanded_data[2*(i + j * bwidth)] = expanded_data[2*(i + j * bwidth)+1] =
				(i >= bitmap.width || j >= bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j];

/*	GLuint texture;
	glGenTextures(1, &texture);

	glBindTexture( GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	// Здесь мы создаем текстуру
	// Помните, что используем GL_LUMINANCE_ALPHA, чтобы было два альфа канала данных
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bwidth, bheight, 0,
		GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data);
*/
	//nInt32 tid = CTextureManager::GetSingeltonPtr()->AddTexture(GL_TEXTURE_2D,
	//	expanded_data, bwidth, bheight, CImageFormats::NF_LUMINANCE_ALPHA);
/*	CTexturePtr ptex = CTextureManager::GetSingeltonPtr()->AddTexture(new CTexture(fname.c_str(), GL_TEXTURE_2D));
	ptex->SetEnvType(GL_MODULATE);
	ptex->CreateTexture(expanded_data, bwidth, bheight, CImageFormats::NF_LUMINANCE_ALPHA, GL_CLAMP);

	// После создания текстуры, мы больше не нуждаемся в промежуточных данных.
	freemems(expanded_data);

	CLetter letter(slot->metrics.horiBearingX >> 6, slot->metrics.horiBearingY >> 6,
		slot->metrics.horiAdvance >> 6, bwidth, bheight, bitmap.width, bitmap.rows,
		code, ptex);

*/
	nstring resnamet;
	nstring resnamei("TempFontImage");
	resnamet = mName + "_" + CStringUtils::IntTo16xString(static_cast<nInt32>(code));
// Создаем промежуточное изображение в памяти
	CImagePtr pImage = CImageManager::GetSingelton().CreateNewImage(resnamei, mName, mem,
		bwidth, bheight, 1, CImageFormats::NF_LUMINANCE_ALPHA, CResource::NV_FREE);
// На базе изображения создаем текстуру
	CTexturePtr texp = CTextureManager::GetSingelton().CreateNewTexture(resnamet, mName, pImage);

	// После создания текстуры, мы больше не нуждаемся в промежуточных данных.
	mem.FreeBuffer();

	CLetter letter(slot->metrics.horiBearingX >> 6, slot->metrics.horiBearingY >> 6,
		slot->metrics.horiAdvance >> 6, bwidth, bheight, bitmap.width, bitmap.rows,
		code, texp);
	mSize += texp->GetSize();

/// Создаем дисплейный список на букву ///////////////////////////////////////////////
	letter.GetDispList().CreateList();
	letter.GetDispList().BeginList();
/// //////////////////////////////////////////////////////////////////////////////////
	if(!texp.IsNull())
		texp->ApplyTexture();

// Вычислим какая часть нашей текстуры будет заполнена пустым пространством.
// Мы рисуем только ту часть текстуры, в которой находится символ, и сохраняем
// информацию в переменных x и y, затем, когда мы рисуем четырехугольник,
// мы будем только ссылаться на ту часть текстуры, в которой непосредственно
// содержится символ.
	nReal x = static_cast<nReal>(letter.GetBitmapw()) / static_cast<nReal>(letter.GetWidth()),
		y = static_cast<nReal>(letter.GetBitmapr()) / static_cast<nReal>(letter.GetHeight());

	//glBindTexture(GL_TEXTURE_2D, let.GetTex());

	glBegin(GL_QUADS);
		glTexCoord2f(0,0);
		glVertex2i(0,0);
		glTexCoord2f(0,y);
		glVertex2i(0,letter.GetBitmapr());
		glTexCoord2f(x,y);
		glVertex2i(letter.GetBitmapw(), letter.GetBitmapr());
		glTexCoord2f(x,0);
		glVertex2i(letter.GetBitmapw(), 0);
	glEnd();

/// Завершаем дисплейный список //////////////////////////////////////////////////
	letter.GetDispList().EndList();
/// //////////////////////////////////////////////////////////////////////////////

	letters_map[code] = letter;
}