extremetuxracer/src/ft_font.h

660 lines
18 KiB
C++

/* --------------------------------------------------------------------
Extreme Tuxracer
Copyright (c) 2001-2004 Henry Maddocks (FTGL)
Copyright (C) 2010 Extreme Tuxracer Team (modification)
The FTGL library from H. Maddocks is published under the terms
of the Lesser General Publish License (LGPL). You can find a
copy of the LGPL on the gnu website:
http://www.gnu.org/copyleft/lesser.html
Hint: almost all comments are removed from the code to make it
shorter. So all modules could put together in a single module.
To read the comments of the author you should download the
original FTGL library. Most functions are the same as in this
module.
--------------------------------------------------------------------- */
#ifndef FTFONT_H
#define FTFONT_H
#include "bh.h"
#include <ft2build.h>
#include FT_OUTLINE_H
typedef double FTGL_DOUBLE;
#ifndef FT_OPEN_MEMORY
#define FT_OPEN_MEMORY (FT_Open_Flags)1
#endif
#ifndef FT_RENDER_MODE_MONO
#define FT_RENDER_MODE_MONO ft_render_mode_mono
#endif
#ifndef FT_RENDER_MODE_NORMAL
#define FT_RENDER_MODE_NORMAL ft_render_mode_normal
#endif
#ifdef _MSC_VER // MS Visual C++
#pragma warning(disable : 4251)
#pragma warning(disable : 4275)
#pragma warning(disable : 4786)
#ifdef FTGL_LIBRARY_STATIC // static lib - no special export required
# define FTGL_EXPORT
#elif FTGL_LIBRARY // dynamic lib - must export/import symbols appropriately.
# define FTGL_EXPORT __declspec(dllexport)
#else
# define FTGL_EXPORT __declspec(dllimport)
#endif
#else
#define FTGL_EXPORT
#endif
// --------------------------------------------------------------------
// FTVector
// --------------------------------------------------------------------
template <typename FT_VECTOR_ITEM_TYPE>
class FTGL_EXPORT FTVector {
public:
typedef FT_VECTOR_ITEM_TYPE value_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef size_t size_type;
FTVector() {
Capacity = Size = 0;
Items = 0;
}
virtual ~FTVector() {clear();}
FTVector &operator = (const FTVector& v) {
reserve(v.capacity());
iterator ptr = begin();
const_iterator vbegin = v.begin();
const_iterator vend = v.end();
while (vbegin != vend) {*ptr++ = *vbegin++;}
Size = v.size();
return *this;
}
size_type size() const {return Size;}
size_type capacity() const {return Capacity;}
iterator begin() {return Items;}
const_iterator begin() const {return Items;}
iterator end() {return begin() + size();}
const_iterator end() const {return begin() + size();}
bool empty() const {return size() == 0;}
reference operator [](size_type pos) {return (*(begin() + pos));}
const_reference operator [](size_type pos) const {return (*(begin() + pos));}
void clear() {
if (Capacity) {
delete [] Items;
Capacity = Size = 0;
Items = 0;
}
}
void reserve(size_type n) {
if (capacity() < n) {expand(n);}
}
void push_back(const value_type& x) {
if (size() == capacity()) {expand();}
(*this)[size()] = x;
++Size;
}
void resize(size_type n, value_type x) {
if (n == size()) {return;}
reserve(n);
iterator begin, end;
if (n >= Size) {
begin = this->end();
end = this->begin() + n;
} else {
begin = this->begin() + n;
end = this->end();
}
while (begin != end) {*begin++ = x;}
Size = n;
}
private:
void expand(size_type capacity_hint = 0) {
size_type new_capacity =(capacity() == 0) ? 256 : capacity()* 2;
if (capacity_hint) {
while (new_capacity < capacity_hint) {new_capacity *= 2;}
}
value_type *new_items = new value_type[new_capacity];
iterator begin = this->begin();
iterator end = this->end();
value_type *ptr = new_items;
while (begin != end) {*ptr++ = *begin++;}
if (Capacity) {delete [] Items;}
Items = new_items;
Capacity = new_capacity;
}
size_type Capacity;
size_type Size;
value_type* Items;
};
// --------------------------------------------------------------------
// FTList
// --------------------------------------------------------------------
template <typename FT_LIST_ITEM_TYPE>
class FTGL_EXPORT FTList {
FTList(const FTList&);
FTList& operator=(const FTList&);
public:
typedef FT_LIST_ITEM_TYPE value_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef size_t size_type;
FTList() : listSize(0), tail(0) {
tail = NULL;
head = new Node;
}
~FTList() {
Node* next;
for (Node *walk = head; walk; walk = next) {
next = walk->next;
delete walk;
}
}
size_type size() const {return listSize;}
void push_back(const value_type& item) {
Node* node = new Node(item);
if (head->next == NULL) {head->next = node;}
if (tail) {tail->next = node;}
tail = node;
++listSize;
}
reference front() const {return head->next->payload;}
reference back() const {return tail->payload;}
private:
struct Node {
Node() : next(NULL) {}
Node(const value_type& item) : next(NULL) {payload = item;}
Node* next;
value_type payload;
};
size_type listSize;
Node* head;
Node* tail;
};
// --------------------------------------------------------------------
// FTCharToGlyphIndexMap
// --------------------------------------------------------------------
class FTGL_EXPORT FTCharToGlyphIndexMap {
public:
typedef unsigned long CharacterCode;
typedef signed long GlyphIndex;
enum {
NumberOfBuckets = 256,
BucketSize = 256,
IndexNotFound = -1
};
FTCharToGlyphIndexMap() {this->Indices = 0;}
virtual ~FTCharToGlyphIndexMap() {
if (this->Indices) {
this->clear();
delete [] this->Indices;
this->Indices = 0;
}
}
void clear() {
if (this->Indices) {
for (int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++) {
if (this->Indices[i]) {
delete [] this->Indices[i];
this->Indices[i] = 0;
}
}
}
}
const GlyphIndex find(CharacterCode c) {
if (!this->Indices) {return 0;}
div_t pos = div(c, FTCharToGlyphIndexMap::BucketSize);
if (!this->Indices[pos.quot]) {return 0;}
const FTCharToGlyphIndexMap::GlyphIndex *ptr = &this->Indices[pos.quot][pos.rem];
if (*ptr == FTCharToGlyphIndexMap::IndexNotFound) {return 0;}
return *ptr;
}
void insert(CharacterCode c, GlyphIndex g) {
if (!this->Indices) {
this->Indices = new GlyphIndex* [FTCharToGlyphIndexMap::NumberOfBuckets];
for (int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++)
{ this->Indices[i] = 0; }
}
div_t pos = div(c, FTCharToGlyphIndexMap::BucketSize);
if (!this->Indices[pos.quot]) {
this->Indices[pos.quot] = new GlyphIndex [FTCharToGlyphIndexMap::BucketSize];
for (int i = 0; i < FTCharToGlyphIndexMap::BucketSize; i++)
{this->Indices[pos.quot][i] = FTCharToGlyphIndexMap::IndexNotFound;}
}
this->Indices[pos.quot][pos.rem] = g;
}
private:
GlyphIndex** Indices;
};
// --------------------------------------------------------------------
// FTLibrary
// --------------------------------------------------------------------
class FTGL_EXPORT FTLibrary {
public:
static const FTLibrary &Instance();
const FT_Library* const GetLibrary() const { return library;}
FT_Error Error() const { return err;}
~FTLibrary();
private:
FTLibrary();
FTLibrary(const FT_Library&) {}
FTLibrary& operator=(const FT_Library&) { return *this; }
bool Initialise();
FT_Library* library;
FT_Error err;
};
// --------------------------------------------------------------------
// FTPoint
// --------------------------------------------------------------------
class FTGL_EXPORT FTPoint {
public:
FTPoint() {
values[0] = 0;
values[1] = 0;
values[2] = 0;
}
FTPoint(const FTGL_DOUBLE x, const FTGL_DOUBLE y, const FTGL_DOUBLE z) {
values[0] = x;
values[1] = y;
values[2] = z;
}
FTPoint(const FT_Vector& ft_vector) {
values[0] = ft_vector.x;
values[1] = ft_vector.y;
values[2] = 0;
}
FTPoint& operator += (const FTPoint& point) {
values[0] += point.values[0];
values[1] += point.values[1];
values[2] += point.values[2];
return *this;
}
FTPoint operator + (const FTPoint& point) {
FTPoint temp;
temp.values[0] = values[0] + point.values[0];
temp.values[1] = values[1] + point.values[1];
temp.values[2] = values[2] + point.values[2];
return temp;
}
FTPoint operator * (double multiplier) {
FTPoint temp;
temp.values[0] = values[0] * multiplier;
temp.values[1] = values[1] * multiplier;
temp.values[2] = values[2] * multiplier;
return temp;
}
friend FTPoint operator*(double multiplier, FTPoint& point);
friend bool operator == (const FTPoint &a, const FTPoint &b);
friend bool operator != (const FTPoint &a, const FTPoint &b);
operator const FTGL_DOUBLE*() const {return values;}
void X(FTGL_DOUBLE x) { values[0] = x;};
void Y(FTGL_DOUBLE y) { values[1] = y;};
void Z(FTGL_DOUBLE z) { values[2] = z;};
FTGL_DOUBLE X() const { return values[0];};
FTGL_DOUBLE Y() const { return values[1];};
FTGL_DOUBLE Z() const { return values[2];};
private:
FTGL_DOUBLE values[3];
};
// --------------------------------------------------------------------
// FTSize
// --------------------------------------------------------------------
class FTGL_EXPORT FTSize {
public:
FTSize();
virtual ~FTSize();
bool CharSize(FT_Face* face, unsigned int point_size,
unsigned int x_resolution, unsigned int y_resolution);
unsigned int CharSize() const;
float Ascender() const;
float Descender() const;
float Height() const;
float Width() const;
float Underline() const;
FT_Error Error() const { return err; }
private:
FT_Face* ftFace;
FT_Size ftSize;
unsigned int size;
unsigned int xResolution;
unsigned int yResolution;
FT_Error err;
};
// --------------------------------------------------------------------
// FTFace
// --------------------------------------------------------------------
class FTGL_EXPORT FTFace {
public:
FTFace(const char* fontFilePath);
FTFace(const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
virtual ~FTFace();
bool Attach(const char* fontFilePath);
bool Attach(const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
FT_Face* Face() const { return ftFace;}
const FTSize& Size(const unsigned int size, const unsigned int res);
unsigned int CharMapCount();
FT_Encoding* CharMapList();
FTPoint KernAdvance(unsigned int index1, unsigned int index2);
FT_GlyphSlot Glyph(unsigned int index, FT_Int load_flags);
unsigned int GlyphCount() const { return numGlyphs;}
FT_Error Error() const { return err; }
private:
FT_Face* ftFace;
FTSize charSize;
int numGlyphs;
FT_Encoding* fontEncodingList;
bool hasKerningTable;
FT_Error err;
};
// --------------------------------------------------------------------
// FTBox
// --------------------------------------------------------------------
class FTGL_EXPORT FTBBox {
public:
FTBBox()
: lowerX(0.0f),
lowerY(0.0f),
lowerZ(0.0f),
upperX(0.0f),
upperY(0.0f),
upperZ(0.0f)
{}
FTBBox(float lx, float ly, float lz, float ux, float uy, float uz)
: lowerX(lx),
lowerY(ly),
lowerZ(lz),
upperX(ux),
upperY(uy),
upperZ(uz)
{}
FTBBox(FT_GlyphSlot glyph)
: lowerX(0.0f),
lowerY(0.0f),
lowerZ(0.0f),
upperX(0.0f),
upperY(0.0f),
upperZ(0.0f) {
FT_BBox bbox;
FT_Outline_Get_CBox(&(glyph->outline), &bbox);
lowerX = static_cast<float>(bbox.xMin) / 64.0f;
lowerY = static_cast<float>(bbox.yMin) / 64.0f;
lowerZ = 0.0f;
upperX = static_cast<float>(bbox.xMax) / 64.0f;
upperY = static_cast<float>(bbox.yMax) / 64.0f;
upperZ = 0.0f;
}
FTBBox &Move(FTPoint distance) {
lowerX += distance.X();
lowerY += distance.Y();
lowerZ += distance.Z();
upperX += distance.X();
upperY += distance.Y();
upperZ += distance.Z();
return *this;
}
~FTBBox() {}
FTBBox &operator += (const FTBBox& bbox) {
lowerX = bbox.lowerX < lowerX? bbox.lowerX: lowerX;
lowerY = bbox.lowerY < lowerY? bbox.lowerY: lowerY;
lowerZ = bbox.lowerZ < lowerZ? bbox.lowerZ: lowerZ;
upperX = bbox.upperX > upperX? bbox.upperX: upperX;
upperY = bbox.upperY > upperY? bbox.upperY: upperY;
upperZ = bbox.upperZ > upperZ? bbox.upperZ: upperZ;
return *this;
}
void SetDepth(float depth) {upperZ = lowerZ + depth;}
float lowerX, lowerY, lowerZ, upperX, upperY, upperZ;
protected:
private:
};
// --------------------------------------------------------------------
// FTGlyph
// --------------------------------------------------------------------
class FTGL_EXPORT FTGlyph {
public:
FTGlyph(FT_GlyphSlot glyph);
virtual ~FTGlyph();
virtual const FTPoint& Render(const FTPoint& pen) = 0;
const FTPoint& Advance() const { return advance;}
const FTBBox& BBox() const { return bBox;}
FT_Error Error() const { return err;}
protected:
FTPoint advance;
FTBBox bBox;
FT_Error err;
private:
};
// --------------------------------------------------------------------
// FTCharmap
// --------------------------------------------------------------------
class FTGL_EXPORT FTCharmap {
public:
FTCharmap(FTFace* face);
virtual ~FTCharmap();
FT_Encoding Encoding() const { return ftEncoding;}
bool CharMap(FT_Encoding encoding);
unsigned int GlyphListIndex(const unsigned int characterCode);
unsigned int FontIndex(const unsigned int characterCode);
void InsertIndex(const unsigned int characterCode, const unsigned int containerIndex);
FT_Error Error() const { return err;}
private:
FT_Encoding ftEncoding;
const FT_Face ftFace;
typedef FTCharToGlyphIndexMap CharacterMap;
CharacterMap charMap;
FT_Error err;
};
// --------------------------------------------------------------------
// FTGlyphContainer
// --------------------------------------------------------------------
class FTGL_EXPORT FTGlyphContainer {
typedef FTVector<FTGlyph*> GlyphVector;
public:
FTGlyphContainer(FTFace* face);
~FTGlyphContainer();
bool CharMap(FT_Encoding encoding);
unsigned int FontIndex(const unsigned int characterCode) const;
void Add(FTGlyph* glyph, const unsigned int characterCode);
const FTGlyph* const Glyph(const unsigned int characterCode) const;
FTBBox BBox(const unsigned int characterCode) const;
float Advance(const unsigned int characterCode, const unsigned int nextCharacterCode);
FTPoint Render(const unsigned int characterCode,
const unsigned int nextCharacterCode, FTPoint penPosition);
FT_Error Error() const { return err;}
private:
FTFace* face;
FTCharmap* charMap;
GlyphVector glyphs;
FT_Error err;
};
// --------------------------------------------------------------------
// FTTextureGlyph
// --------------------------------------------------------------------
class FTGL_EXPORT FTTextureGlyph : public FTGlyph {
public:
FTTextureGlyph(FT_GlyphSlot glyph, int id, int xOffset, int yOffset,
GLsizei width, GLsizei height);
virtual ~FTTextureGlyph();
virtual const FTPoint& Render(const FTPoint& pen);
static void ResetActiveTexture() { activeTextureID = 0;}
private:
int destWidth;
int destHeight;
FTPoint pos;
FTPoint uv[2];
int glTextureID;
static GLint activeTextureID;
};
// --------------------------------------------------------------------
// FTFont
// --------------------------------------------------------------------
class FTGL_EXPORT FTFont {
public:
FTFont(const char* fontFilePath);
FTFont(const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
virtual ~FTFont();
bool Attach(const char* fontFilePath);
bool Attach(const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
bool CharMap(FT_Encoding encoding);
unsigned int CharMapCount();
FT_Encoding* CharMapList();
virtual bool FaceSize(const unsigned int size, const unsigned int res = 72);
unsigned int FaceSize() const;
virtual void Depth(float depth) {}
float Ascender() const;
float Descender() const;
float LineHeight() const;
void BBox(const char* string, float& llx, float& lly,
float& llz, float& urx, float& ury, float& urz);
void BBox(const wchar_t* string, float& llx, float& lly,
float& llz, float& urx, float& ury, float& urz);
float Advance(const wchar_t* string);
float Advance(const char* string);
virtual void Render(const char* string);
virtual void Render(const wchar_t* string);
FT_Error Error() const { return err;}
protected:
virtual FTGlyph* MakeGlyph(unsigned int g) = 0;
FTFace face;
FTSize charSize;
FT_Error err;
private:
inline bool CheckGlyph(const unsigned int chr);
FTGlyphContainer* glyphList;
FTPoint pen;
};
// --------------------------------------------------------------------
// FTTextureFont
// --------------------------------------------------------------------
class FTGL_EXPORT FTGLTextureFont : public FTFont {
public:
FTGLTextureFont(const char* fontFilePath);
FTGLTextureFont(const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
virtual ~FTGLTextureFont();
virtual bool FaceSize(const unsigned int size, const unsigned int res = 72);
virtual void Render(const char* string);
virtual void Render(const wchar_t* string);
private:
inline virtual FTGlyph* MakeGlyph(unsigned int glyphIndex);
inline void CalculateTextureSize();
inline GLuint CreateTexture();
GLsizei maximumGLTextureSize;
GLsizei textureWidth;
GLsizei textureHeight;
FTVector<GLuint> textureIDList;
int glyphHeight;
int glyphWidth;
unsigned int padding;
unsigned int numGlyphs;
unsigned int remGlyphs;
int xOffset;
int yOffset;
};
class FTGL_EXPORT FTGLPixmapFont : public FTFont {
public:
FTGLPixmapFont(const char* fontFilePath);
FTGLPixmapFont(const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
~FTGLPixmapFont();
void Render(const char* string);
void Render(const wchar_t* string);
private:
inline virtual FTGlyph* MakeGlyph(unsigned int g);
};
class FTGL_EXPORT FTPixmapGlyph : public FTGlyph {
public:
FTPixmapGlyph(FT_GlyphSlot glyph);
virtual ~FTPixmapGlyph();
virtual const FTPoint& Render(const FTPoint& pen);
private:
int destWidth;
int destHeight;
FTPoint pos;
unsigned char* data;
};
#endif