/*
CGUITTFont FreeType class for Irrlicht
Copyright (c) 2009-2010 John Norman
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
The original version of this class can be located at:
http://irrlicht.suckerfreegames.com/
John Norman
john@suckerfreegames.com
*/
#include <irrlicht.h>
#include "CGUITTFont.h"
namespace irr
{
namespace gui
{
// Manages the FT_Face cache.
struct SGUITTFace : public virtual irr::IReferenceCounted
{
SGUITTFace() : face_buffer(0), face_buffer_size(0)
{
memset((void*)&face, 0, sizeof(FT_Face));
}
~SGUITTFace()
{
FT_Done_Face(face);
delete[] face_buffer;
}
FT_Face face;
FT_Byte* face_buffer;
FT_Long face_buffer_size;
};
// Static variables.
FT_Library CGUITTFont::c_library;
core::map<io::path, SGUITTFace*> CGUITTFont::c_faces;
bool CGUITTFont::c_libraryLoaded = false;
scene::IMesh* CGUITTFont::shared_plane_ptr_ = 0;
scene::SMesh CGUITTFont::shared_plane_;
//
video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const
{
// Determine what our texture size should be.
// Add 1 because textures are inclusive-exclusive.
core::dimension2du d(bits.width + 1, bits.rows + 1);
core::dimension2du texture_size;
//core::dimension2du texture_size(bits.width + 1, bits.rows + 1);
// Create and load our image now.
video::IImage* image = 0;
switch (bits.pixel_mode)
{
case FT_PIXEL_MODE_MONO:
{
// Create a blank image and fill it with transparent pixels.
texture_size = d.getOptimalSize(true, true);
image = driver->createImage(video::ECF_A1R5G5B5, texture_size);
image->fill(video::SColor(0, 255, 255, 255));
// Load the monochrome data in.
const u32 image_pitch = image->getPitch() / sizeof(u16);
u16* image_data = (u16*)image->lock();
u8* glyph_data = bits.buffer;
for (s32 y = 0; y < bits.rows; ++y)
{
u16* row = image_data;
for (s32 x = 0; x < bits.width; ++x)
{
// Monochrome bitmaps store 8 pixels per byte. The left-most pixel is the bit 0x80.
// So, we go through the data each bit at a time.
if ((glyph_data[y * bits.pitch + (x / 8)] & (0x80 >> (x % 8))) != 0)
*row = 0xFFFF;
++row;
}
image_data += image_pitch;
}
image->unlock();
break;
}
case FT_PIXEL_MODE_GRAY:
{
// Create our blank image.
texture_size = d.getOptimalSize(!driver->queryFeature(video::EVDF_TEXTURE_NPOT), !driver->queryFeature(video::EVDF_TEXTURE_NSQUARE), true, 0);
image = driver->createImage(video::ECF_A8R8G8B8, texture_size);
image->fill(video::SColor(0, 255, 255, 255));
// Load the grayscale data in.
const float gray_count = static_cast<float>(bits.num_grays);
const u32 image_pitch = image->getPitch() / sizeof(u32);
u32* image_data = (u32*)image->lock();
u8* glyph_data = bits.buffer;
for (s32 y = 0; y < bits.rows; ++y)
{
u8* row = glyph_data;
for (s32 x = 0; x < bits.width; ++x)
{
image_data[y * image_pitch + x] |= static_cast<u32>(255.0f * (static_cast<float>(*row++) / gray_count)) << 24;
//data[y * image_pitch + x] |= ((u32)(*bitsdata++) << 24);
}
glyph_data += bits.pitch;
}
image->unlock();
break;
}
default:
// TODO: error message?
return 0;
}
return image;
}
void SGUITTGlyph::preload(u32 char_index, FT_Face face, video::IVideoDriver* driver, u32 font_size, const FT_Int32 loadFlags)
{
if (isLoaded) return;
// Set the size of the glyph.
FT_Set_Pixel_Sizes(face, 0, font_size);
// Attempt to load the glyph.
if (FT_Load_Glyph(face, char_index, loadFlags) != FT_Err_Ok)
// TODO: error message?
return;
FT_GlyphSlot glyph = face->glyph;
FT_Bitmap bits = glyph->bitmap;
// Setup the glyph information here:
advance = glyph->advance;
offset = core::vector2di(glyph->bitmap_left, glyph->bitmap_top);
// Try to get the last page with available slots.
CGUITTGlyphPage* page = parent->getLastGlyphPage();
// If we need to make a new page, do that now.
if (!page)
{
page = parent->createGlyphPage(bits.pixel_mode);
if (!page)
// TODO: add error message?
return;
}
glyph_page = parent->getLastGlyphPageIndex();
u32 texture_side_length = page->texture->getOriginalSize().Width;
core::vector2di page_position(
(page->used_slots % (texture_side_length / font_size)) * font_size,
(page->used_slots / (texture_side_length / font_size)) * font_size
);
source_rect.UpperLeftCorner = page_position;
source_rect.LowerRightCorner = core::vector2di(page_position.X + bits.width, page_position.Y + bits.rows);
page->dirty = true;
++page->used_slots;
--page->available_slots;
// We grab the glyph bitmap here so the data won't be removed when the next glyph is loaded.
surface = createGlyphImage(bits, driver);
// Set our glyph as loaded.
isLoaded = true;
}
void SGUITTGlyph::unload()
{
if (surface)
{
surface->drop();
surface = 0;
}
isLoaded = false;
}
//////////////////////
CGUITTFont* CGUITTFont::createTTFont(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias, const bool transparency)
{
if (!c_libraryLoaded)
{
if (FT_Init_FreeType(&c_library))
return 0;
c_libraryLoaded = true;
}
CGUITTFont* font = new CGUITTFont(env);
bool ret = font->load(filename, size, antialias, transparency);
if (!ret)
{
font->drop();
return 0;
}
return font;
}
CGUITTFont* CGUITTFont::createTTFont(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias, const bool transparency)
{
if (!c_libraryLoaded)
{
if (FT_Init_FreeType(&c_library))
return 0;
c_libraryLoaded = true;
}
CGUITTFont* font = new CGUITTFont(device->getGUIEnvironment());
font->Device = device;
bool ret = font->load(filename, size, antialias, transparency);
if (!ret)
{
font->drop();
return 0;
}
return font;
}
CGUITTFont* CGUITTFont::create(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias, const bool transparency)
{
return CGUITTFont::createTTFont(env, filename, size, antialias, transparency);
}
CGUITTFont* CGUITTFont::create(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias, const bool transparency)
{
return CGUITTFont::createTTFont(device, filename, size, antialias, transparency);
}
//////////////////////
//! Constructor.
CGUITTFont::CGUITTFont(IGUIEnvironment *env)
: use_monochrome(false), use_transparency(true), use_hinting(true), use_auto_hinting(true),
batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
{
#ifdef _DEBUG
setDebugName("CGUITTFont");
#endif
if (Environment)
{
// don't grab environment, to avoid circular references
Driver = Environment->getVideoDriver();
}
if (Driver)
Driver->grab();
setInvisibleCharacters(L" ");
// Glyphs aren't reference counted, so don't try to delete them when we free the array.
Glyphs
Irrlicht之载入irr文件和自定义场景节点(演示程序+源代码)
5星 · 超过95%的资源 需积分: 9 94 浏览量
2013-11-22
20:02:03
上传
评论
收藏 2.24MB 7Z 举报
彩阳
- 粉丝: 2169
- 资源: 102
- 1
- 2
前往页