First past integrat of Max Rhiener work on wrapping FTGL to create osgText

library and demo.
This commit is contained in:
Robert Osfield 2001-10-23 19:51:39 +00:00
parent 63bb05e6fd
commit 8e1b1bcfc1
44 changed files with 4988 additions and 0 deletions

View File

@ -0,0 +1,102 @@
# Microsoft Developer Studio Project File - Name="osgTextDemo" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=osgTextDemo - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "osgTextDemo.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "osgTextDemo.mak" CFG="osgTextDemo - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "osgTextDemo - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "osgTextDemo - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "osgTextDemo - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x807 /d "NDEBUG"
# ADD RSC /l 0x807 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 osgText.lib osgGlut.lib glut32.lib osgUtil.lib osgDB.lib osg.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../../../../osgDev/bin/osgTextDemo.exe"
!ELSEIF "$(CFG)" == "osgTextDemo - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /vd0 /GR /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x807 /d "_DEBUG"
# ADD RSC /l 0x807 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 osgTextd.lib osgGlutd.lib glut32.lib osgUtild.lib osgDBd.lib osgd.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../../osgDev/bin/osgTextDemoD.exe" /pdbtype:sept
!ENDIF
# Begin Target
# Name "osgTextDemo - Win32 Release"
# Name "osgTextDemo - Win32 Debug"
# Begin Group "Quellcodedateien"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\..\src\Demos\osgText\main.cpp
# End Source File
# End Group
# Begin Group "Header-Dateien"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Ressourcendateien"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@ -0,0 +1,115 @@
# Microsoft Developer Studio Project File - Name="osgText" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=osgText - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "osgText.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "osgText.mak" CFG="osgText - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "osgText - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "osgText - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "osgText - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "../../lib"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OSGTEXT_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OSGTEXT_LIBRARY" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x807 /d "NDEBUG"
# ADD RSC /l 0x807 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 ftglDllD.lib glu32.lib opengl32.lib osg.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../../../../osgDev/bin/osgText.dll"
!ELSEIF "$(CFG)" == "osgText - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "../../lib"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OSGTEXT_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /vd0 /GR /GX /ZI /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "OSGTEXT_LIBRARY" /FR /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x807 /d "_DEBUG"
# ADD RSC /l 0x807 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 ftglDllD.lib glu32.lib opengl32.lib osgd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\development\osgDev\osgDev\bin\osgTextD.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "osgText - Win32 Release"
# Name "osgText - Win32 Debug"
# Begin Group "Quellcodedateien"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\src\osgText\Text.cpp
# End Source File
# End Group
# Begin Group "Header-Dateien"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\include\osgText\Export
# End Source File
# Begin Source File
SOURCE=..\..\include\osgText\Text.h
# End Source File
# End Group
# Begin Group "Ressourcendateien"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

25
include/osgText/Export Normal file
View File

@ -0,0 +1,25 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSGTEXT_EXPORT_
#define OSGTEXT_EXPORT_ 1
#ifdef WIN32
#pragma warning( disable : 4251 )
#pragma warning( disable : 4275 )
#pragma warning( disable : 4786 )
#endif
#if defined(_MSC_VER)
# ifdef OSGTEXT_LIBRARY
# define OSGTEXT_EXPORT __declspec(dllexport)
# else
# define OSGTEXT_EXPORT __declspec(dllimport)
# endif /* OSGTEXT_LIBRARY */
#else
# define OSGTEXT_EXPORT
#endif
#endif

345
include/osgText/Text Normal file
View File

@ -0,0 +1,345 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
/* --------------------------------------------------------------------------
*
* openscenegraph textLib / FTGL wrapper
*
* --------------------------------------------------------------------------
*
* prog: max rheiner;mrn@paus.ch
* date: 4/25/2001 (m/d/y)
*
* --------------------------------------------------------------------------
*
* --------------------------------------------------------------------------
*/
#ifndef OSGTEXT_TEXT
#define OSGTEXT_TEXT 1
#include <string>
#include <osg/GL>
#include <osg/Object>
#include <osg/Drawable>
#include <osg/Vec3>
#include <osg/Vec2>
// http://homepages.paradise.net.nz/henryj/code/
/*
#include <FTFace.h>
#include <FTGLBitmapFont.h>
#include <FTGLPixmapFont.h>
#include <FTGLOutlineFont.h>
#include <FTGLPolygonFont.h>
#include <FTGLTextureFont.h>
*/
#include <osgText/Export>
class FTFont;
namespace osgText {
using namespace osg;
///////////////////////////////////////////////////////////////////////////////
// Font - FontBaseClass
class OSGTEXT_EXPORT Font:public Object
{
public:
Font();
virtual bool open(const std::string& font);
virtual bool create(int pointSize, const unsigned int res = 72 );
virtual bool create();
virtual void output(const char* text);
virtual bool isOk(void) const { return _init; }
virtual bool isCreated(void) const { return isOk() && _created; }
virtual float getWidth(const char* text) const;
virtual int getHeight() const;
virtual int getDescender() const;
virtual int getAscender() const;
int getPointSize(void) const { return _pointSize; }
const std::string& getFontName();
FTFont* getFont(void) { return _font; }
protected:
virtual ~Font();
virtual void clear();
virtual FTFont* createFontObj(void)=0;
bool init(const std::string& font);
bool _init;
bool _created;
FTFont* _font;
std::string _fontName;
int _pointSize;
int _res;
};
// Font
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// RasterFont
class OSGTEXT_EXPORT RasterFont:public Font
{
public:
RasterFont():Font(){;}
RasterFont(const std::string& font):Font(){;}
protected:
};
// RasterFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// VectorFont
class OSGTEXT_EXPORT VectorFont:public Font
{
public:
VectorFont():Font(){;}
VectorFont(const std::string& font):Font(){;}
protected:
double _precision;
};
// VectorFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// BitmapFont
class OSGTEXT_EXPORT BitmapFont:public RasterFont
{
public:
BitmapFont() {;}
BitmapFont(const std::string& font,
int point_size);
META_Object(BitmapFont);
protected:
virtual FTFont* createFontObj(void);
};
// BitmapFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// PixmapFont
class OSGTEXT_EXPORT PixmapFont:public RasterFont
{
public:
PixmapFont() {;}
PixmapFont(const std::string& font,
int point_size);
META_Object(PixmapFont);
protected:
virtual FTFont* createFontObj(void);
};
// PixmapFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// TextureFont
class OSGTEXT_EXPORT TextureFont:public RasterFont
{
public:
TextureFont() {;}
TextureFont(const std::string& font,
int point_size);
META_Object(TextureFont);
protected:
virtual FTFont* createFontObj(void);
};
// PixmapFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// OutlineFont
class OSGTEXT_EXPORT OutlineFont:public VectorFont
{
public:
OutlineFont() {;}
OutlineFont(const std::string& font,
int point_size,
double precision);
META_Object(OutlineFont);
protected:
virtual FTFont* createFontObj(void);
};
// OutlineFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// PolygonFont
class OSGTEXT_EXPORT PolygonFont:public VectorFont
{
public:
PolygonFont() {;}
PolygonFont(const std::string& font,
int point_size,
double precision);
META_Object(PolygonFont);
protected:
virtual FTFont* createFontObj(void);
};
// PolygonFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Text
class OSGTEXT_EXPORT Text:public Drawable
{
public:
enum AlignmentType
{ // from left to right, top to bottom
LEFT_TOP,
LEFT_CENTER,
LEFT_BOTTOM,
CENTER_TOP,
CENTER_CENTER,
CENTER_BOTTOM,
RIGHT_TOP,
RIGHT_CENTER,
RIGHT_BOTTOM,
};
enum BoundingBoxType
{
GEOMETRY,
GLYPH,
};
enum DrawModeType
{ // from left to right, top to bottom
TEXT = 1<<0,
BOUNDINGBOX = 1<<1,
ALIGNEMENT = 1<<2,
DEFAULT = TEXT,
};
Text();
Text(Font* font);
META_Object(Text);
void setPosition(const Vec3& pos);
void setPosition(const Vec2& pos);
void setDrawMode(int mode) { _drawMode=mode; }
int getDrawMode(void) { return _drawMode; }
void setBoundingBox(int mode);
int getBoundingBox(void) { return _boundingBoxType; }
void setAlignement(int alignement);
int getAlignement(void) { return _alignement; }
void setFont(Font* font);
Font* getFont(void);
void setText(const char* text) { _text=text; }
void setText(std::string& text) { _text=text; }
const std::string& getText() const { return _text; }
virtual void drawImmediateMode(State& state);
virtual void drawBoundingBox(void);
virtual void drawAlignement(void);
const Vec3& getPosition() { return _pos; }
const Vec3& getAlignementPos() { return _alignementPos; };
protected:
enum FontType
{
UNDEF,
BITMAP,
PIXMAP,
OUTLINE,
POLYGON,
TEXTURE,
};
virtual ~Text();
virtual void setDefaults(void);
virtual const bool computeBound(void) const;
virtual void calcBounds(Vec3* min,Vec3* max) const;
void initAlignement(Vec3* min,Vec3* max);
bool initAlignement(void);
ref_ptr<Font> _font;
bool _init;
bool _initAlignement;
std::string _text;
int _fontType;
int _alignement;
int _drawMode;
int _boundingBoxType;
Vec3 _pos;
Vec3 _alignementPos;
};
// Text
///////////////////////////////////////////////////////////////////////////////
};
#endif // _OSG_TEXT_H

588
src/Demos/osgtext/main.cpp Normal file
View File

@ -0,0 +1,588 @@
/* --------------------------------------------------------------------------
*
* osgText demo
*
* --------------------------------------------------------------------------
*
* prog: max rheiner;mrn@paus.ch
* date: 4/26/2001 (m/d/y)
*
* --------------------------------------------------------------------------
*/
#include <osg/Node>
#include <osg/StateSet>
#include <osg/GeoSet>
#include <osg/Material>
#include <osg/Transparency>
#include <osg/Transform>
#include <osg/PolygonMode>
#include <osg/Notify>
#include <osgUtil/TrackballManipulator>
#include <osgUtil/FlightManipulator>
#include <osgUtil/DriveManipulator>
#include <osgGLUT/Viewer>
#include <GL/glut.h>
#include <osgText/text.h>
#include <vector>
///////////////////////////////////////////////////////////////////////////////
// globals
#define TEXT_POLYGON "Polygon Font - jygq"
#define TEXT_OUTLINE "Outline Font - jygq"
#define TEXT_TEXTURE "Texture Font - jygq"
#define TEXT_BITMAP "Bitmap Font - jygq"
#define TEXT_PIXMAP "Pixmap Font - jygq"
#define TEXT_COL_2D osg::Vec4(.9,.9,.9,1)
#define TEXT_COL_3D osg::Vec4(.99,.3,.2,1)
std::string ttfPath("./fonts/times.ttf");
std::string ttfPath1("./fonts/verdana.ttf");
int gFontSize=18;
int gFontSize1=24;
std::vector<osg::ref_ptr<osgText::Text > > gTextList;
osgText::Text::AlignmentType gAlignement=osgText::Text::AlignmentType::LEFT_BOTTOM;
void set2dScene(osg::Group* rootNode)
{
osgText::Text* text;
osg::Geode* geode;
osg::Material* textMaterial;
osg::Vec4 textColor;
osg::StateSet* textState;
double xOffset=250;
double yOffset=gFontSize+10;
///////////////////////////////////////////////////////////////////////////
// setup the texts
///////////////////////////////////////////////////////////////////////////
// BitmapFont
osgText::BitmapFont* bitmapFont=new osgText::BitmapFont(ttfPath,
gFontSize1);
text=new osgText::Text(bitmapFont);
gTextList.push_back(text);
text->setText(std::string("2d ")+std::string(TEXT_BITMAP));
text->setPosition(osg::Vec3(xOffset,yOffset,0));
text->setDrawMode( osgText::Text::DrawModeType::TEXT |
osgText::Text::DrawModeType::BOUNDINGBOX |
osgText::Text::DrawModeType::ALIGNEMENT );
text->setAlignement(gAlignement);
geode = new osg::Geode();
geode->setName("BitmapFont");
geode->addDrawable( text );
textMaterial = new osg::Material();
textMaterial->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE);
textMaterial->setDiffuse( osg::Material::FRONT_AND_BACK, TEXT_COL_2D);
textState = new osg::StateSet();
textState->setAttribute(textMaterial );
geode->setStateSet( textState );
rootNode->addChild(geode);
xOffset+=90;
yOffset+=120;
///////////////////////////////////////////////////////////////////////////
// PixmapFont
osgText::PixmapFont* pixmapFont=new osgText::PixmapFont(ttfPath,
gFontSize1);
text=new osgText::Text(pixmapFont);
gTextList.push_back(text);
text->setText(std::string("2d ")+std::string(TEXT_PIXMAP));
text->setPosition(osg::Vec3(xOffset,yOffset,0));
text->setDrawMode( osgText::Text::DrawModeType::TEXT |
osgText::Text::DrawModeType::BOUNDINGBOX |
osgText::Text::DrawModeType::ALIGNEMENT );
text->setAlignement(gAlignement);
geode = new osg::Geode();
geode->setName("PixmapFont");
geode->addDrawable( text );
textMaterial = new osg::Material();
textMaterial->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE);
textMaterial->setDiffuse( osg::Material::FRONT_AND_BACK,TEXT_COL_2D);
// to get antiaA pixmapFonts we have to draw them with blending
osg::Transparency *transp=new osg::Transparency();
transp->setFunction(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
textState = new osg::StateSet();
textState->setAttribute(textMaterial );
textState->setAttribute(transp);
textState->setMode(GL_BLEND,osg::StateAttribute::ON);
textState->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
geode->setStateSet( textState );
rootNode->addChild(geode);
xOffset+=90;
yOffset+=120;
///////////////////////////////////////////////////////////////////////////
// TextureFont
osgText::TextureFont* textureFont=new osgText::TextureFont(ttfPath1,
gFontSize1);
text=new osgText::Text(textureFont);
gTextList.push_back(text);
text->setText(std::string("2d ")+std::string(TEXT_TEXTURE));
text->setPosition(osg::Vec3(xOffset,yOffset,0));
text->setDrawMode( osgText::Text::DrawModeType::TEXT |
osgText::Text::DrawModeType::BOUNDINGBOX |
osgText::Text::DrawModeType::ALIGNEMENT );
text->setAlignement(gAlignement);
geode = new osg::Geode();
geode->setName("TextureFont");
geode->addDrawable( text );
textMaterial = new osg::Material();
textMaterial->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE);
textMaterial->setDiffuse( osg::Material::FRONT_AND_BACK, TEXT_COL_2D);
// to get antiaA pixmapFonts we have to draw them with blending
transp=new osg::Transparency();
transp->setFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
textState = new osg::StateSet();
textState->setAttribute(textMaterial );
textState->setAttribute(transp);
textState->setMode(GL_TEXTURE_2D,osg::StateAttribute::ON);
textState->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
geode->setStateSet( textState );
rootNode->addChild(geode);
xOffset+=90;
yOffset+=120;
///////////////////////////////////////////////////////////////////////////
// PolygonFont
osgText::PolygonFont* polygonFont=new osgText::PolygonFont(ttfPath,
gFontSize1,
3);
text=new osgText::Text(polygonFont);
gTextList.push_back(text);
text->setText(std::string("2d ")+std::string("TEXT_POLYGON"));
text->setPosition(osg::Vec3(xOffset,yOffset,0));
text->setDrawMode( osgText::Text::DrawModeType::TEXT |
osgText::Text::DrawModeType::BOUNDINGBOX |
osgText::Text::DrawModeType::ALIGNEMENT );
text->setAlignement(gAlignement);
geode = new osg::Geode();
geode->setName("PolygonFont");
geode->addDrawable( text );
textMaterial = new osg::Material();
textMaterial->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE);
textMaterial->setDiffuse( osg::Material::FRONT_AND_BACK, TEXT_COL_2D);
textState = new osg::StateSet();
textState->setAttribute(textMaterial );
geode->setStateSet( textState );
rootNode->addChild(geode);
xOffset+=90;
yOffset+=120;
///////////////////////////////////////////////////////////////////////////
// OutlineFont
osgText::OutlineFont* outlineFont=new osgText::OutlineFont(ttfPath,
gFontSize1,
3);
text=new osgText::Text(outlineFont);
gTextList.push_back(text);
text->setText(std::string("2d ")+std::string(TEXT_OUTLINE));
text->setPosition(osg::Vec3(xOffset,yOffset,0));
text->setDrawMode( osgText::Text::DrawModeType::TEXT |
osgText::Text::DrawModeType::BOUNDINGBOX |
osgText::Text::DrawModeType::ALIGNEMENT );
text->setAlignement(gAlignement);
geode = new osg::Geode();
geode->setName("OutlineFont");
geode->addDrawable( text );
textMaterial = new osg::Material();
textMaterial->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE);
textMaterial->setDiffuse( osg::Material::FRONT_AND_BACK, TEXT_COL_2D);
textState = new osg::StateSet();
textState->setAttribute(textMaterial );
geode->setStateSet( textState );
rootNode->addChild(geode);
}
void setScene(osg::Group* rootNode)
{
osgText::Text* text;
osg::Geode* geode;
osg::Material* textMaterial;
osg::Vec4 textColor;
osg::StateSet* textState;
double xOffset=0;
double yOffset=0;
///////////////////////////////////////////////////////////////////////////
// setup the texts
///////////////////////////////////////////////////////////////////////////
// BitmapFont
osgText::BitmapFont* bitmapFont=new osgText::BitmapFont(ttfPath,
gFontSize);
text=new osgText::Text(bitmapFont);
gTextList.push_back(text);
text->setText(std::string(TEXT_BITMAP));
text->setPosition(osg::Vec3(xOffset,yOffset,0));
text->setDrawMode( osgText::Text::DrawModeType::TEXT |
osgText::Text::DrawModeType::BOUNDINGBOX |
osgText::Text::DrawModeType::ALIGNEMENT );
text->setAlignement(gAlignement);
geode = new osg::Geode();
geode->setName("BitmapFont");
geode->addDrawable( text );
textMaterial = new osg::Material();
textMaterial->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE);
textMaterial->setDiffuse( osg::Material::FRONT_AND_BACK,TEXT_COL_3D);
textState = new osg::StateSet();
textState->setAttribute(textMaterial );
geode->setStateSet( textState );
rootNode->addChild(geode);
yOffset+=gFontSize+5;
///////////////////////////////////////////////////////////////////////////
// PixmapFont
osgText::PixmapFont* pixmapFont=new osgText::PixmapFont(ttfPath,
gFontSize);
text=new osgText::Text(pixmapFont);
gTextList.push_back(text);
text->setText(std::string(TEXT_PIXMAP));
text->setPosition(osg::Vec3(xOffset,yOffset,0));
text->setDrawMode( osgText::Text::DrawModeType::TEXT |
osgText::Text::DrawModeType::BOUNDINGBOX |
osgText::Text::DrawModeType::ALIGNEMENT );
text->setAlignement(gAlignement);
geode = new osg::Geode();
geode->setName("PixmapFont");
geode->addDrawable( text );
textMaterial = new osg::Material();
textMaterial->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE);
textMaterial->setDiffuse( osg::Material::FRONT_AND_BACK,TEXT_COL_3D);
// to get antiaA pixmapFonts we have to draw them with blending
osg::Transparency *transp=new osg::Transparency();
transp->setFunction(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
textState = new osg::StateSet();
textState->setAttribute(textMaterial );
textState->setAttribute(transp);
textState->setMode(GL_BLEND,osg::StateAttribute::ON);
textState->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
geode->setStateSet( textState );
rootNode->addChild(geode);
yOffset+=gFontSize+5;
///////////////////////////////////////////////////////////////////////////
// TextureFont
osgText::TextureFont* textureFont=new osgText::TextureFont(ttfPath,
gFontSize);
text=new osgText::Text(textureFont);
gTextList.push_back(text);
text->setText(std::string(TEXT_TEXTURE));
text->setPosition(osg::Vec3(xOffset,yOffset,0));
text->setDrawMode( osgText::Text::DrawModeType::TEXT |
osgText::Text::DrawModeType::BOUNDINGBOX |
osgText::Text::DrawModeType::ALIGNEMENT );
text->setAlignement(gAlignement);
geode = new osg::Geode();
geode->setName("TextureFont");
geode->addDrawable( text );
textMaterial = new osg::Material();
textMaterial->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE);
textMaterial->setDiffuse( osg::Material::FRONT_AND_BACK,TEXT_COL_3D);
// to get antiaA pixmapFonts we have to draw them with blending
transp=new osg::Transparency();
transp->setFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
textState = new osg::StateSet();
textState->setAttribute(textMaterial );
textState->setAttribute(transp);
// textState->setMode(GL_BLEND,osg::StateAttribute::ON);
textState->setMode(GL_TEXTURE_2D,osg::StateAttribute::ON);
textState->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
geode->setStateSet( textState );
rootNode->addChild(geode);
yOffset+=gFontSize+5;
///////////////////////////////////////////////////////////////////////////
// PolygonFont
osgText::PolygonFont* polygonFont=new osgText::PolygonFont(ttfPath,
gFontSize,
3);
text=new osgText::Text(polygonFont);
gTextList.push_back(text);
text->setText(std::string(TEXT_POLYGON));
text->setPosition(osg::Vec3(xOffset,yOffset,0));
text->setDrawMode( osgText::Text::DrawModeType::TEXT |
osgText::Text::DrawModeType::BOUNDINGBOX |
osgText::Text::DrawModeType::ALIGNEMENT );
text->setAlignement(gAlignement);
geode = new osg::Geode();
geode->setName("PolygonFont");
geode->addDrawable( text );
textMaterial = new osg::Material();
textMaterial->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE);
textMaterial->setDiffuse( osg::Material::FRONT_AND_BACK,TEXT_COL_3D);
textState = new osg::StateSet();
textState->setAttribute(textMaterial );
geode->setStateSet( textState );
rootNode->addChild(geode);
yOffset+=gFontSize+5;
///////////////////////////////////////////////////////////////////////////
// OutlineFont
osgText::OutlineFont* outlineFont=new osgText::OutlineFont(ttfPath,
gFontSize,
3);
text=new osgText::Text(outlineFont);
gTextList.push_back(text);
text->setText(std::string(TEXT_OUTLINE));
text->setPosition(osg::Vec3(xOffset,yOffset,0));
text->setDrawMode( osgText::Text::DrawModeType::TEXT |
osgText::Text::DrawModeType::BOUNDINGBOX |
osgText::Text::DrawModeType::ALIGNEMENT );
text->setAlignement(gAlignement);
geode = new osg::Geode();
geode->setName("OutlineFont");
geode->addDrawable( text );
textMaterial = new osg::Material();
textMaterial->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE);
textMaterial->setDiffuse( osg::Material::FRONT_AND_BACK,TEXT_COL_3D);
textState = new osg::StateSet();
textState->setAttribute(textMaterial );
geode->setStateSet( textState );
rootNode->addChild(geode);
}
class TextViewer: public osgGLUT::Viewer
{
public:
virtual float app(unsigned int viewport)
{
float ret;
ret=Viewer::app(viewport);
if(_hudSceneView.valid() && viewport>=_viewportList.size()-1)
{
_hudSceneView->app();
}
return ret;
}
virtual float cull(unsigned int viewport)
{
float ret;
ret=Viewer::cull(viewport);
if(_hudSceneView.valid() && viewport>=_viewportList.size()-1)
_hudSceneView->cull();
return ret;
}
virtual float draw(unsigned int viewport)
{
float ret;
ret=Viewer::draw(viewport);
if(_hudSceneView.valid() && viewport>=_viewportList.size()-1)
_hudSceneView->draw();
return ret;
}
void addHUD(osg::Node* rootnode)
{
_hudSceneView = new osgUtil::SceneView;
_hudSceneView->setDefaults();
_hudSceneView->setSceneData(rootnode);
}
virtual void reshape(GLint w, GLint h)
{
Viewer::reshape(w,h);
if(_hudSceneView.valid())
{
_hudSceneView->setViewport(0,0,w,h);
_hudCam->setOrtho2D(0,w,0,h);
}
}
virtual bool open()
{
bool ret=Viewer::open();
// set the clear flag / after the visualReq.Visitor
if(_hudSceneView.valid())
{
_hudSceneView->getRenderStage()->setClearMask(0);
_hudSceneView->getCullVisitor()->setCullingMode(osgUtil::CullViewState::NO_CULLING);
_hudSceneView->setCalcNearFar(false);
_hudCam=new osg::Camera;
// leftBottom
_hudSceneView->setCamera(_hudCam.get());
}
return ret;
}
protected:
osg::ref_ptr<osg::Camera> _hudCam;
osg::ref_ptr<osgUtil::SceneView> _hudSceneView;
virtual void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case '1':
{ // change DrawMode
std::vector<osg::ref_ptr<osgText::Text> >::iterator itr=gTextList.begin();
for(;itr!=gTextList.end();itr++)
(*itr)->setDrawMode(osgText::Text::DrawModeType::TEXT ^ (*itr)->getDrawMode());
}
return;
case '2':
{ // change DrawMode
std::vector<osg::ref_ptr<osgText::Text> >::iterator itr=gTextList.begin();
for(;itr!=gTextList.end();itr++)
(*itr)->setDrawMode(osgText::Text::DrawModeType::BOUNDINGBOX ^ (*itr)->getDrawMode());
}
return;
case '3':
{ // change DrawMode
std::vector<osg::ref_ptr<osgText::Text> >::iterator itr=gTextList.begin();
for(;itr!=gTextList.end();itr++)
(*itr)->setDrawMode(osgText::Text::DrawModeType::ALIGNEMENT ^ (*itr)->getDrawMode());
}
return;
///////////////////////////////////////////////////////////////////
case '4':
{ // change BoundingBoxType to GEOMETRY
std::vector<osg::ref_ptr<osgText::Text> >::iterator itr=gTextList.begin();
osgText::Text::BoundingBoxType type=(*itr)->getBoundingBox()==osgText::Text::BoundingBoxType::GLYPH ?
osgText::Text::BoundingBoxType::GEOMETRY :
osgText::Text::BoundingBoxType::GLYPH;
for(;itr!=gTextList.end();itr++)
(*itr)->setBoundingBox(type);
}
return;
///////////////////////////////////////////////////////////////////
case '5':
{ // change the textAlignement
gAlignement=(osgText::Text::AlignmentType)((int)gAlignement+1);
if(gAlignement>osgText::Text::AlignmentType::RIGHT_BOTTOM)
gAlignement=osgText::Text::AlignmentType::LEFT_TOP;
std::vector<osg::ref_ptr<osgText::Text> >::iterator itr=gTextList.begin();
for(;itr!=gTextList.end();itr++)
(*itr)->setAlignement(gAlignement);
}
return;
default:
Viewer::keyboard(key,x,y);
};
}
};
int main( int argc, char **argv )
{
// initialize the GLUT
glutInit( &argc, argv );
// get the fontName
if(argc > 1)
ttfPath=argv[1];
if(argc > 2)
ttfPath1=argv[2];
if(argc > 3)
{
gFontSize=atoi(argv[3]);
if(gFontSize<=4)
gFontSize=8;
}
if(argc > 4)
{
gFontSize1=atoi(argv[3]);
if(gFontSize1<=4)
gFontSize1=8;
}
osg::Group* rootNode = new osg::Group;
osg::Group* scene2d = new osg::Group;
osg::Transform* textGroup = new osg::Transform;
// set the name for the hole group
rootNode->setName("sceneGroup");
// turn off the culling
// turn off the light
osg::StateSet* gstate = new osg::StateSet;
gstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
gstate->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
gstate->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
rootNode->setStateSet(gstate);
scene2d->setStateSet(gstate);
// setup the sceneData
setScene(textGroup);
textGroup->preRotate(-90,1,0,0);
rootNode->addChild(textGroup);
// setup the 2dNode
set2dScene(scene2d);
// initialize the viewer.
TextViewer viewer;
/*
viewer.addViewport( rootNode );
viewer.getViewportSceneView(0)->setBackgroundColor(osg::Vec4(.2,.2,.2,1));
*/
viewer.addViewport( rootNode,0.0,0.0,0.5,0.5);
viewer.addViewport( rootNode,0.5,0.0,0.5,0.5);
viewer.addViewport( rootNode,0.0,0.5,1.0,0.5);
viewer.addHUD(scene2d);
// register trackball, flight and drive.
viewer.registerCameraManipulator(new osgUtil::TrackballManipulator);
viewer.registerCameraManipulator(new osgUtil::FlightManipulator);
viewer.registerCameraManipulator(new osgUtil::DriveManipulator);
viewer.open();
viewer.run();
return 0;
}

View File

@ -0,0 +1,76 @@
#include "GL/gl.h"
#include "FTBitmapGlyph.h"
#include "FTGL.h"
FTBitmapGlyph::FTBitmapGlyph( FT_Glyph glyph)
: FTGlyph(),
destWidth(0),
destHeight(0),
data(0)
{
// This function will always fail if the glyph's format isn't scalable????
FT_Error err = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_mono, 0, 1);
if( err || ft_glyph_format_bitmap != glyph->format)
{return;}
FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
FT_Bitmap* source = &bitmap->bitmap;
//check the pixel mode
//ft_pixel_mode_grays
int srcWidth = source->width;
int srcHeight = source->rows;
int srcPitch = source->pitch;
advance = glyph->advance.x >> 16;
pos.x = bitmap->left;
pos.y = srcHeight - bitmap->top;
// FIXME What about dest alignment?
destWidth = srcWidth;
destHeight = srcHeight;
data = new unsigned char[srcPitch * destHeight];
for(int y = 0; y < srcHeight; ++y)
{
--destHeight;
for(int x = 0; x < srcPitch; ++x)
{
*( data + ( destHeight * srcPitch + x)) = *( source->buffer + ( y * srcPitch) + x);
}
}
destHeight = srcHeight;
// discard glyph image (bitmap or not)
// Is this the right place to do this?
FT_Done_Glyph( glyph );
}
FTBitmapGlyph::~FTBitmapGlyph()
{
delete[] data;
}
float FTBitmapGlyph::Render( const FT_Vector& pen)
{
if( data != 0 )
{
// Move the glyph origin
glBitmap( 0, 0, 0.0, 0.0, pen.x + pos.x, pen.y - pos.y, (const GLubyte *)0 );
glBitmap( destWidth, destHeight, 0.0f, 0.0, 0.0, 0.0, (const GLubyte *)data);
// Restore the glyph origin
glBitmap( 0, 0, 0.0, 0.0, -pen.x - pos.x, -pen.y + pos.y, (const GLubyte *)0 );
}
return advance;
}

View File

@ -0,0 +1,48 @@
#ifndef __FTBitmapGlyph__
#define __FTBitmapGlyph__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include "FTGlyph.h"
class FTBitmapGlyph : public FTGlyph
{
public:
/**
* Constructor
*
* @param
*/
FTBitmapGlyph( FT_Glyph glyph);
/**
*
*/
virtual ~FTBitmapGlyph();
/**
*
* @param pen
*
* @return
*/
virtual float Render( const FT_Vector& pen);
// attributes
private:
// methods
// attributes
int destWidth;
int destHeight;
unsigned char* data;
};
#endif // __FTBitmapGlyph__

91
src/osgText/FTCharmap.cc Normal file
View File

@ -0,0 +1,91 @@
#include "FTCharmap.h"
FTCharmap::FTCharmap( FT_Face face)
: err(0),
ftFace( face)
{
ftEncoding = face->charmap->encoding;
}
FTCharmap::~FTCharmap()
{
charMap.clear();
}
bool FTCharmap::CharMap( FT_Encoding encoding)
{
if( ftEncoding == encoding)
{
return true;
}
err = FT_Select_Charmap( ftFace, encoding );
if( !err)
{
ftEncoding = encoding;
charMap.clear();
}
return !err;
}
bool FTCharmap::CharMap( FT_UShort platform, FT_UShort encoding)
{
FT_CharMap found = 0;
FT_CharMap charmap;
for( int n = 0; n < ftFace->num_charmaps; n++ )
{
charmap = ftFace->charmaps[n];
if( charmap->platform_id == platform && charmap->encoding_id == encoding)
{
found = charmap;
break;
}
}
if( !found )
{
return false;
}
if( ftEncoding == found->encoding)
{
return true;
}
/* now, select the charmap for the face object */
err = FT_Set_Charmap( ftFace, found );
if( !err)
{
ftEncoding = found->encoding;
charMap.clear();
}
return !err;
}
unsigned int FTCharmap::CharIndex( unsigned int index )
{
CharacterMap::const_iterator result = charMap.find( index);
if( result == charMap.end())
{
unsigned int glyph = FT_Get_Char_Index( ftFace, index);
charMap.insert( CharacterMap::value_type( index, glyph));
return glyph;
}
else
{
return result->second;
}
}

109
src/osgText/FTCharmap.h Normal file
View File

@ -0,0 +1,109 @@
#ifndef __FTCharmap__
#define __FTCharmap__
#include <map>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
//#include "FTGL.h"
using namespace std;
/**
* FTCharmap
*
*
*/
class FTCharmap
{
public:
/**
* Constructor
*/
FTCharmap( FT_Face ftFace);
/**
* Destructor
*/
virtual ~FTCharmap();
/**
* Queries for the current character map code.
*
* @return The current character map code.
*/
FT_Encoding Encoding() const { return ftEncoding;}
/**
* Sets the character map for the face.
* Valid encodings as at Freetype 2.0.4
* ft_encoding_none
* ft_encoding_symbol
* ft_encoding_unicode
* ft_encoding_latin_2
* ft_encoding_sjis
* ft_encoding_gb2312
* ft_encoding_big5
* ft_encoding_wansung
* ft_encoding_johab
* ft_encoding_adobe_standard
* ft_encoding_adobe_expert
* ft_encoding_adobe_custom
* ft_encoding_apple_roman
*
* @param encoding the Freetype encoding symbol. See above.
* @return <code>true</code> if charmap was valid
* and set correctly
*/
bool CharMap( FT_Encoding encoding);
/**
* Sets the character map for the face.
*
* @param encoding the Freetype encoding symbol. See above.
* @return <code>true</code> if charmap was valid
* and set correctly
*/
bool CharMap( FT_UShort platform, FT_UShort encoding);
/**
* Get the glyph index of the input character.
*
* @param index The character code of the requested glyph in the
* current encoding eg apple roman.
* @return The glyph index for the character.
*/
unsigned int CharIndex( unsigned int index );
/**
* Queries for errors.
*
* @return The current error code.
*/
FT_Error Error() const { return err;}
protected:
/**
* Current character map code.
*/
FT_Encoding ftEncoding;
FT_Face ftFace;
typedef map< unsigned long, unsigned long> CharacterMap;
CharacterMap charMap;
/**
* Current error code. Zero means no error.
*/
FT_Error err;
private:
};
#endif // __FTCharmap__

110
src/osgText/FTFace.cc Normal file
View File

@ -0,0 +1,110 @@
#include "FTFace.h"
#include "FTLibrary.h"
#include "FTCharmap.h"
#include "FTGL.h"
FTFace::FTFace()
: ftFace(0),
numCharMaps(0),
charMap(0),
numGlyphs(0),
err(0)
{}
FTFace::~FTFace()
{
delete charMap;
charMap = 0;
Close();
}
bool FTFace::Open( const char* filename)
{
ftFace = new FT_Face;
err = FT_New_Face( *FTLibrary::Instance().GetLibrary(), filename, 0, ftFace);
if( err)
{
delete ftFace;
ftFace = 0;
return false;
}
else
{
charMap = new FTCharmap( *ftFace);
return true;
}
}
void FTFace::Close()
{
if( ftFace)
{
FT_Done_Face( *ftFace);
delete ftFace;
ftFace = 0;
}
}
FTSize& FTFace::Size( const unsigned int size, const unsigned int res)
{
if( !charSize.CharSize( ftFace, size, res, res))
{
err = charSize.Error();
}
return charSize;
}
bool FTFace::CharMap( FT_Encoding encoding)
{
return charMap->CharMap( encoding);
}
unsigned int FTFace::CharIndex( unsigned int index) const
{
return charMap->CharIndex( index);
}
FT_Vector& FTFace::KernAdvance( unsigned int index1, unsigned int index2)
{
kernAdvance.x = 0; kernAdvance.y = 0;
if( FT_HAS_KERNING((*ftFace)) && index1 && index2)
{
err = FT_Get_Kerning( *ftFace, index1, index2, ft_kerning_unfitted, &kernAdvance);
if( !err)
{
kernAdvance.x /= 64; kernAdvance.y /= 64;
}
}
return kernAdvance;
}
FT_Glyph* FTFace::Glyph( unsigned int index, FT_Int load_flags)
{
err = FT_Load_Glyph( *ftFace, index, load_flags);
err = FT_Get_Glyph( (*ftFace)->glyph, &ftGlyph);
if( !err)
{
return &ftGlyph;
}
else
{
return NULL;
}
}

144
src/osgText/FTFace.h Normal file
View File

@ -0,0 +1,144 @@
#ifndef __FTFace__
#define __FTFace__
//#include "FTGL.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include "FTSize.h"
class FTCharmap;
/**
* FTFace class provides an abstraction layer for the Freetype Face.
*
* @see "Freetype 2 Documentation - 2.0.4"
*
*/
class FTFace
{
public:
/**
* Default Constructor
*/
FTFace();
/**
* Destructor
*
* Disposes of the current Freetype Face.
*/
virtual ~FTFace();
/**
* Opens and reads a face file.
*
* @param fontname font file name.
* @return <code>true</code> if file has opened
* successfully.
*/
bool Open( const char* filename);
/**
* Disposes of the face
*/
void Close();
/**
* Sets the char size for the current face.
*
* This doesn't guarantee that the size was set correctly. Clients
* should check errors.
*
* @param size the face size in points (1/72 inch)
* @param res the resolution of the target device.
* @return <code>FTSize</code> object
*/
FTSize& Size( const unsigned int size, const unsigned int res);
/**
* Sets the character map for the face.
*
* @param encoding the Freetype encoding symbol. See above.
* @return <code>true</code> if charmap was valid
* and set correctly
*/
bool CharMap( FT_Encoding encoding);
/**
* Get the glyph index of the input character.
*
* @param index The character code of the requested glyph in the
* current encoding eg apple roman.
* @return The glyph index for the character.
*/
unsigned int CharIndex( unsigned int index ) const;
/**
* Gets the kerning vector between two glyphs
*/
FT_Vector& KernAdvance( unsigned int index1, unsigned int index2);
/**
* Loads and creates a Freetype glyph.
*/
FT_Glyph* Glyph( unsigned int index, FT_Int load_flags);
/**
* Gets the current Freetype face.
*/
FT_Face* Face() const { return ftFace;}
/**
* Queries for errors.
*
* @return The current error code.
*/
FT_Error Error() const { return err; }
private:
/**
* The size object associated with this face
*/
FTSize charSize;
/**
* The Character Map object associated with this face
*/
FTCharmap* charMap;
/**
* The Freetype face
*/
FT_Face* ftFace;
/**
* Temporary variable to hold a glyph
*/
FT_Glyph ftGlyph;
/**
* The number of character maps in this face.
*/
int numCharMaps;
/**
* The number of glyphs in this face
*/
int numGlyphs;
/**
* Temporary variable to holding a kerning vector.
*/
FT_Vector kernAdvance;
/**
* Current error code. Zero means no error.
*/
FT_Error err;
};
#endif // __FTFace__

148
src/osgText/FTFont.cc Normal file
View File

@ -0,0 +1,148 @@
#include "FTFace.h"
#include "FTFont.h"
#include "FTGlyphContainer.h"
#include "FTGL.h"
FTFont::FTFont()
: numFaces(0),
glyphList(0),
err(0)
{
pen.x = 0;
pen.y = 0;
}
FTFont::~FTFont()
{
Close();
}
bool FTFont::Open( const char* fontname )
{
if( face.Open( fontname))
{
FT_Face* ftFace = face.Face();
numGlyphs = (*ftFace)->num_glyphs;
return true;
}
else
{
err = face.Error();
return false;
}
}
void FTFont::Close()
{
delete glyphList;
}
bool FTFont::FaceSize( const unsigned int size, const unsigned int res )
{
charSize = face.Size( size, res);
if( glyphList)
delete glyphList;
glyphList = new FTGlyphContainer( &face, numGlyphs);
if( MakeGlyphList())
{
return true;
}
else
{
return false;
}
}
bool FTFont::CharMap( FT_Encoding encoding)
{
err = face.CharMap( encoding);
return !err;
}
int FTFont::Ascender() const
{
return charSize.Ascender();
}
int FTFont::Descender() const
{
return charSize.Descender();
}
float FTFont::Advance( const wchar_t* string)
{
const wchar_t* c = string; // wchar_t IS unsigned?
float width = 0;
while( *c)
{
width += glyphList->Advance( *c, *(c + 1));
++c;
}
return width;
}
float FTFont::Advance( const char* string)
{
const unsigned char* c = (unsigned char*)string; // This is ugly, what is the c++ way?
float width = 0;
while( *c)
{
width += glyphList->Advance( *c, *(c + 1));
++c;
}
return width;
}
void FTFont::render( const char* string )
{
const unsigned char* c = (unsigned char*)string; // This is ugly, what is the c++ way?
FT_Vector kernAdvance;
pen.x = 0; pen.y = 0;
while( *c)
{
kernAdvance = glyphList->render( *c, *(c + 1), pen);
pen.x += kernAdvance.x;
pen.y += kernAdvance.y;
++c;
}
}
void FTFont::render( const wchar_t* string )
{
const wchar_t* c = string; // wchar_t IS unsigned?
FT_Vector kernAdvance;
pen.x = 0; pen.y = 0;
while( *c)
{
kernAdvance = glyphList->render( *c, *(c + 1), pen);
pen.x += kernAdvance.x;
pen.y += kernAdvance.y;
++c;
}
}

179
src/osgText/FTFont.h Normal file
View File

@ -0,0 +1,179 @@
#ifndef __FTFont__
#define __FTFont__
#include <string>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "FTFace.h"
#include "FTGL.h"
class FTGlyphContainer;
using namespace std;
/**
* FTFont is the public interface for the FTGL library.
*
* Specific font classes are derived from this class. It uses the helper
* classes FTFace and FTSize to access the Freetype library. This class
* is abstract and deriving classes must implement the protected
* <code>MakeGlyphList</code> function to build a glyphList with the
* appropriate glyph type.
*
* @see FTFace
* @see FTSize
* @see FTGlyphContainer
* @see FTGlyph
*/
class FTFont
{
public:
/**
* Default Constructor
*/
FTFont();
/**
* Destructor
*/
virtual ~FTFont();
/**
* Opens and reads a font file.
*
* @param fontname font file name.
* @return <code>true</code> if file has opened
* successfully.
*/
virtual bool Open( const char* fontname );
/**
* Disposes of the font
*/
virtual void Close();
/**
* Sets the char size for the current face.
*
* @param size the face size in points (1/72 inch)
* @param res the resolution of the target device.
* @return <code>true</code> if size was set correctly
*/
virtual bool FaceSize( const unsigned int size, const unsigned int res = 72 );
/**
* Sets the character map for the face.
*
* @param encoding Freetype enumerate for char map code.
* @return <code>true</code> if charmap was valid and
* set correctly
*/
virtual bool CharMap( FT_Encoding encoding );
/**
* Gets the global ascender height for the face.
*
* @return Ascender height
*/
virtual int Ascender() const;
/**
* Gets the global descender height for the face.
*
* @return Descender height
*/
virtual int Descender() const;
/**
* Gets the advance width for a string.
*
* param string a wchar_t string
* @return advance width
*/
float Advance( const wchar_t* string);
/**
* Gets the advance width for a string.
*
* param string a char string
* @return advance width
*/
float Advance( const char* string);
/**
* Renders a string of characters
*
* @param string 'C' style string to be output.
*/
virtual void render( const char* string );
/**
* Renders a string of characters
*
* @param string wchar_t string to be output.
*/
virtual void render( const wchar_t* string );
/**
* Queries the Font for errors.
*
* @return The current error code.
*/
virtual FT_Error Error() const { return err;}
protected:
/**
* Constructs the internal glyph cache.
*
* This a list of glyphs processed for openGL rendering NOT
* freetype glyphs
*/
virtual bool MakeGlyphList() = 0;
/**
* Current face object
*/
FTFace face;
/**
* Number of faces in this font
*/
int numFaces;
/**
* Current size object
*/
FTSize charSize;
/**
* An object that holds a list of glyphs
*/
FTGlyphContainer* glyphList;
/**
* The number of glyphs in this font
*/
int numGlyphs;
/**
* Current pen or cursor position;
*/
FT_Vector pen;
/**
* Current error code. Zero means no error.
*/
FT_Error err;
private:
};
#endif // __FTFont__

7
src/osgText/FTGL.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef __FTGL__
#define __FTGL__
// For Future?
#endif // __FTGL__

View File

@ -0,0 +1,70 @@
#include "GL/gl.h"
#include "FTGLBitmapFont.h"
#include "FTGlyphContainer.h"
#include "FTBitmapGlyph.h"
FTGLBitmapFont::FTGLBitmapFont()
: tempGlyph(0)
{}
FTGLBitmapFont::~FTGLBitmapFont()
{}
// OPSignature: bool FTGlyphContainer:MakeGlyphList()
bool FTGLBitmapFont::MakeGlyphList()
{
// if( preCache)
for( unsigned int c = 0; c < numGlyphs; ++c)
{
FT_Glyph* ftGlyph = face.Glyph( c, FT_LOAD_DEFAULT);
// FT_HAS_VERTICAL(face)
if( ftGlyph)
{
tempGlyph = new FTBitmapGlyph( *ftGlyph);
glyphList->Add( tempGlyph);
}
else
{
err = face.Error();
}
}
return !err;
}
void FTGLBitmapFont::render( const char* string)
{
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT);
// doing this every frame is a bad?
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE);
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
FTFont::render( string);
glPopClientAttrib();
}
void FTGLBitmapFont::render( const wchar_t* string)
{
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT);
// doing this every frame is a bad?
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE);
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
FTFont::render( string);
glPopClientAttrib();
}

View File

@ -0,0 +1,59 @@
#ifndef __FTGLBitmapFont__
#define __FTGLBitmapFont__
#include "FTFont.h"
class FTBitmapGlyph;
/**
* FTGLBitmapFont is a specialisation of the FTFont class for handling
* Bitmap fonts
*
* @see FTFont
*/
class FTGLBitmapFont : public FTFont
{
public:
/**
* Constructor
*/
FTGLBitmapFont();
/**
* Destructor
*/
~FTGLBitmapFont();
/**
* Renders a string of characters
*
* @param string 'C' style string to be output.
*/
void render( const char* string);
/**
* Renders a string of characters
*
* @param string 'C' style string to be output.
*/
void render( const wchar_t* string);
// attributes
private:
/**
* Constructs the internal glyph cache.
*
* This a list of glyphs processed for openGL rendering NOT
* freetype glyphs
*/
bool MakeGlyphList();
/**
* Temp variable for a FTBitmapGlyph
*/
FTBitmapGlyph* tempGlyph;
};
#endif // __FTGLBitmapFont__

View File

@ -0,0 +1,68 @@
#include "GL/gl.h"
#include "FTGLOutlineFont.h"
#include "FTGlyphContainer.h"
#include "FTGL.h"
#include "FTOutlineGlyph.h"
FTGLOutlineFont::FTGLOutlineFont()
: tempGlyph(0)
{}
FTGLOutlineFont::~FTGLOutlineFont()
{}
bool FTGLOutlineFont::MakeGlyphList()
{
for( unsigned int n = 0; n < numGlyphs; ++n)
{
FT_Glyph* ftGlyph = face.Glyph( n, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
if( ftGlyph)
{
tempGlyph = new FTOutlineGlyph( *ftGlyph);
glyphList->Add( tempGlyph);
}
else
{
err = face.Error();
}
}
return !err;
}
void FTGLOutlineFont::render( const char* string)
{
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
glEnable( GL_LINE_SMOOTH);
glHint( GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
FTFont::render( string);
glPopAttrib();
}
void FTGLOutlineFont::render( const wchar_t* string)
{
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
glEnable( GL_LINE_SMOOTH);
glHint( GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
FTFont::render( string);
glPopAttrib();
}

View File

@ -0,0 +1,37 @@
#ifndef __FTGLOutlineFont
#define __FTGLOutlineFont
#include "FTFont.h"
#include "FTGL.h"
class FTOutlineGlyph;
/**
* FTGLOutlineFont is a specialisation of the FTFont class for handling
* Vector Outline fonts
*
* @see FTFont
*/
class FTGLOutlineFont : public FTFont
{
public:
// methods
FTGLOutlineFont();
~FTGLOutlineFont();
void render( const char* string);
void render( const wchar_t* string);
// attributes
private:
// methods
bool MakeGlyphList();
// attributes
FTOutlineGlyph* tempGlyph;
};
#endif

View File

@ -0,0 +1,66 @@
#include "GL/gl.h"
#include "FTGLPixmapFont.h"
#include "FTGlyphContainer.h"
#include "FTPixmapGlyph.h"
FTGLPixmapFont::FTGLPixmapFont()
: tempGlyph(0)
{}
FTGLPixmapFont::~FTGLPixmapFont()
{}
// OPSignature: bool FTGlyphContainer:MakeGlyphList()
bool FTGLPixmapFont::MakeGlyphList()
{
// if( preCache)
for( unsigned int c = 0; c < numGlyphs; ++c)
{
FT_Glyph* ftGlyph = face.Glyph( c, FT_LOAD_DEFAULT);
// FT_HAS_VERTICAL(face)
if( ftGlyph)
{
tempGlyph = new FTPixmapGlyph( *ftGlyph);
glyphList->Add( tempGlyph);
}
else
{
err = face.Error();
}
}
return !err;
}
void FTGLPixmapFont::render( const char* string)
{
glPushAttrib( GL_ENABLE_BIT | GL_PIXEL_MODE_BIT);
glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
FTFont::render( string);
glPopAttrib();
}
void FTGLPixmapFont::render( const wchar_t* string)
{
glPushAttrib( GL_ENABLE_BIT | GL_PIXEL_MODE_BIT);
glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
FTFont::render( string);
glPopAttrib();
}

View File

@ -0,0 +1,36 @@
#ifndef __FTGLPixmapFont__
#define __FTGLPixmapFont__
#include "FTFont.h"
class FTPixmapGlyph;
/**
* FTGLPixmapFont is a specialisation of the FTFont class for handling
* Pixmap (Grey Scale) fonts
*
* @see FTFont
*/
class FTGLPixmapFont : public FTFont
{
public:
// methods
FTGLPixmapFont();
~FTGLPixmapFont();
void render( const char* string);
void render( const wchar_t* string);
private:
// methods
bool MakeGlyphList();
// attributes
FTPixmapGlyph* tempGlyph;
};
#endif // __FTGLPixmapFont__

View File

@ -0,0 +1,35 @@
#include "FTGLPolygonFont.h"
#include "FTGlyphContainer.h"
#include "FTGL.h"
#include "FTPolyGlyph.h"
FTGLPolygonFont::FTGLPolygonFont()
: tempGlyph(0)
{}
FTGLPolygonFont::~FTGLPolygonFont()
{}
bool FTGLPolygonFont::MakeGlyphList()
{
for( unsigned int n = 0; n < numGlyphs; ++n)
{
FT_Glyph* ftGlyph = face.Glyph( n, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
if( ftGlyph)
{
tempGlyph = new FTPolyGlyph( *ftGlyph);
glyphList->Add( tempGlyph);
}
else
{
err = face.Error();
}
}
return !err;
}

View File

@ -0,0 +1,35 @@
#ifndef __FTGLPolygonFont__
#define __FTGLPolygonFont__
#include "FTFont.h"
#include "FTGL.h"
class FTPolyGlyph;
/**
* FTGLPolygonFont is a specialisation of the FTFont class for handling
* tesselated Polygon Mesh fonts
*
* @see FTFont
*/
class FTGLPolygonFont : public FTFont
{
public:
// methods
FTGLPolygonFont();
~FTGLPolygonFont();
// attributes
private:
// methods
bool MakeGlyphList();
// attributes
FTPolyGlyph* tempGlyph;
};
#endif // __FTGLPolygonFont__

View File

@ -0,0 +1,210 @@
#include "GL/gl.h"
#include "FTGLTextureFont.h"
#include "FTGlyphContainer.h"
#include "FTGL.h"
#include "FTTextureGlyph.h"
using namespace std;
typedef unsigned long UInt32; // a mac thing?
inline UInt32 NextPowerOf2( UInt32 in)
{
in -= 1;
in |= in >> 16;
in |= in >> 8;
in |= in >> 4;
in |= in >> 2;
in |= in >> 1;
return in + 1;
}
FTGLTextureFont::FTGLTextureFont()
: numTextures(1),
textMem(0),
padding(1),
tempGlyph(0),
maxTextSize(0),
textureWidth(0),
textureHeight(0),
glyphHeight(0),
glyphWidth(0)
{}
FTGLTextureFont::~FTGLTextureFont()
{
glDeleteTextures( numTextures, (const GLuint*)glTextureID);
}
bool FTGLTextureFont::MakeGlyphList()
{
if( !maxTextSize)
glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&maxTextSize);
glyphHeight = ( charSize.Height()) + padding;
glyphWidth = ( charSize.Width()) + padding;
GetSize();
int totalMem;
if( textureHeight > maxTextSize)
{
numTextures = static_cast<int>( textureHeight / maxTextSize) + 1;
if( numTextures > 15) // FIXME
numTextures = 15;
int heightRemain = NextPowerOf2( textureHeight % maxTextSize);
totalMem = ((maxTextSize * ( numTextures - 1)) + heightRemain) * textureWidth;
glGenTextures( numTextures, (GLuint*)&glTextureID[0]);
textMem = new unsigned char[totalMem]; // GL_ALPHA texture;
memset( textMem, 0, totalMem);
unsigned int glyphNum = 0;
unsigned char* currTextPtr = textMem;
for( int x = 0; x < numTextures - 1; ++x)
{
glyphNum = FillGlyphs( glyphNum, glTextureID[x], textureWidth, maxTextSize, currTextPtr);
CreateTexture( x, textureWidth, maxTextSize, currTextPtr);
currTextPtr += ( textureWidth * maxTextSize);
++glyphNum;
}
glyphNum = FillGlyphs( glyphNum, glTextureID[numTextures - 1], textureWidth, heightRemain, currTextPtr);
CreateTexture( numTextures - 1, textureWidth, heightRemain, currTextPtr);
}
else
{
textureHeight = NextPowerOf2( textureHeight);
totalMem = textureWidth * textureHeight;
glGenTextures( numTextures, (GLuint*)&glTextureID[0]);
textMem = new unsigned char[totalMem]; // GL_ALPHA texture;
std::memset( textMem, 0, totalMem);
FillGlyphs( 0, glTextureID[0], textureWidth, textureHeight, textMem);
CreateTexture( 0, textureWidth, textureHeight, textMem);
}
delete [] textMem;
return !err;
}
unsigned int FTGLTextureFont::FillGlyphs( unsigned int glyphStart, int id, int width, int height, unsigned char* textdata)
{
int currentTextX = padding;
int currentTextY = padding;// + padding;
float currTextU = (float)padding / (float)width;
float currTextV = (float)padding / (float)height;
// numGlyphs = 256; // FIXME hack
unsigned int n;
for( n = glyphStart; n <= numGlyphs; ++n)
{
FT_Glyph* ftGlyph = face.Glyph( n, FT_LOAD_NO_HINTING);
if( ftGlyph)
{
unsigned char* data = textdata + (( currentTextY * width) + currentTextX);
currTextU = (float)currentTextX / (float)width;
tempGlyph = new FTTextureGlyph( *ftGlyph, id, data, width, height, currTextU, currTextV);
glyphList->Add( tempGlyph);
currentTextX += glyphWidth;
if( currentTextX > ( width - glyphWidth))
{
currentTextY += glyphHeight;
if( currentTextY > ( height - glyphHeight))
return n;
currentTextX = padding;
currTextV = (float)currentTextY / (float)height;
}
}
else
{
err = face.Error();
}
}
return n;
}
void FTGLTextureFont::GetSize()
{
//work out the max width. Most likely maxTextSize
textureWidth = NextPowerOf2( numGlyphs * glyphWidth);
if( textureWidth > maxTextSize)
{
textureWidth = maxTextSize;
}
int h = static_cast<int>( textureWidth / glyphWidth);
textureHeight = (( numGlyphs / h) + 1) * glyphHeight;
}
void FTGLTextureFont::CreateTexture( int id, int width, int height, unsigned char* data)
{
glPixelStorei( GL_UNPACK_ALIGNMENT, 1); //What does this do exactly?
glBindTexture( GL_TEXTURE_2D, glTextureID[id]);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
}
void FTGLTextureFont::render( const char* string)
{
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
glBindTexture( GL_TEXTURE_2D, (GLuint)FTTextureGlyph::activeTextureID);
// QUADS are faster!? Less function call overhead?
glBegin( GL_QUADS);
FTFont::render( string);
glEnd();
glPopAttrib();
}
void FTGLTextureFont::render( const wchar_t* string)
{
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
glBindTexture( GL_TEXTURE_2D, (GLuint)FTTextureGlyph::activeTextureID);
// QUADS are faster!? Less function call overhead?
glBegin( GL_QUADS);
FTFont::render( string);
glEnd();
glPopAttrib();
}

View File

@ -0,0 +1,54 @@
#ifndef __FTGLTextureFont
#define __FTGLTextureFont
#include "FTFont.h"
#include "FTGL.h"
class FTTextureGlyph;
/**
* FTGLTextureFont is a specialisation of the FTFont class for handling
* Texture mapped fonts
*
* @see FTFont
*/
class FTGLTextureFont : public FTFont
{
public:
// methods
FTGLTextureFont();
virtual ~FTGLTextureFont();
virtual int TextureWidth() const { return textureWidth;}
virtual int TextureHeight() const { return textureHeight;}
virtual void render( const char* string);
virtual void render( const wchar_t* string);
private:
// attributes
FTTextureGlyph* tempGlyph;
long maxTextSize;
int textureWidth;
int textureHeight;
unsigned long glTextureID[16];
int numTextures;
unsigned char* textMem;
int glyphHeight;
int glyphWidth;
int padding;
// methods
bool MakeGlyphList();
void CreateTexture( int id, int width, int height, unsigned char* data);
void GetSize();
unsigned int FillGlyphs( unsigned int glyphStart, int textID, int textureWidth, int textureHeight, unsigned char* textMem);
};
#endif

14
src/osgText/FTGlyph.cc Normal file
View File

@ -0,0 +1,14 @@
#include "FTGlyph.h"
FTGlyph::FTGlyph()
: advance(0),
err(0)
{
pos.x = 0;
pos.y = 0;
}
FTGlyph::~FTGlyph()
{}

76
src/osgText/FTGlyph.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef __FTGlyph__
#define __FTGlyph__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
//#include "FTGL.h"
/**
* FTGlyph is the base clas for FTGL glyphs.
*
* It provides the interface between Freetype glyphs and their openGL
* renderable counterparts. This is an abstract class and derived classes
* must implement the <code>render</code> function.
*
* @see FTGlyphContainer
*
*/
class FTGlyph
{
public:
/**
* Constructor
*/
FTGlyph();
/**
* Destructor
*/
virtual ~FTGlyph();
/**
* Renders this glyph at the current pen position.
*
* @param pen The current pen position.
* @return The advance distance for this glyph.
*/
virtual float Render( const FT_Vector& pen) = 0;
/**
* Return the advance width for this glyph.
*
* @return advance width.
*/
float Advance() const { return advance;}
/**
* Queries for errors.
*
* @return The current error code.
*/
FT_Error Error() const { return err;}
protected:
/**
* The advance distance for this glyph
*/
float advance;
/**
* Vector from the pen position to the topleft corner of the glyph
*/
FT_Vector pos;
/**
* Current error code. Zero means no error.
*/
FT_Error err;
private:
};
#endif // __FTGlyph__

View File

@ -0,0 +1,66 @@
#include "FTGlyphContainer.h"
#include "FTGlyph.h"
#include "FTFace.h"
FTGlyphContainer::FTGlyphContainer( FTFace* f, int g, bool p)
: preCache( p),
numGlyphs( g),
face( f),
err( 0)
{
glyphs.reserve( g);
}
FTGlyphContainer::~FTGlyphContainer()
{
vector<FTGlyph*>::iterator iter;
for( iter = glyphs.begin(); iter != glyphs.end(); ++iter)
{
delete *iter;
}
glyphs.clear();
}
bool FTGlyphContainer::Add( FTGlyph* tempGlyph)
{
// At the moment we are using a vector. Vectors don't return bool.
glyphs.push_back( tempGlyph);
return true;
}
float FTGlyphContainer::Advance( unsigned int index, unsigned int next)
{
unsigned int left = face->CharIndex( index);
unsigned int right = face->CharIndex( next);
float width = face->KernAdvance( left, right).x;
width += glyphs[left]->Advance();
return width;
}
FT_Vector& FTGlyphContainer::render( unsigned int index, unsigned int next, FT_Vector pen)
{
kernAdvance.x = 0; kernAdvance.y = 0;
unsigned int left = face->CharIndex( index);
unsigned int right = face->CharIndex( next);
kernAdvance = face->KernAdvance( left, right);
if( !face->Error())
{
advance = glyphs[left]->Render( pen);
}
kernAdvance.x = advance + kernAdvance.x; // FIXME float to long
// kernAdvance.y = advance.y + kernAdvance.y;
return kernAdvance;
}

View File

@ -0,0 +1,100 @@
#ifndef __FTGlyphContainer__
#define __FTGlyphContainer__
#include <vector>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
//#include "FTGL.h"
class FTFace;
class FTGlyph;
using namespace std;
/**
* FTGlyphContainer
*
* @see FTGlyph
*/
class FTGlyphContainer
{
public:
/**
* Constructor
*/
FTGlyphContainer( FTFace* face, int numGlyphs, bool p = false);
/**
* Destructor
*/
~FTGlyphContainer();
/**
* Adds a glyph to this glyph list.
*
* @param glyph
* @return <code>true</code>
*/
bool Add( FTGlyph* glyph);
/**
* Returns the kerned advance width for a glyph.
*
* param index glyph index of the character
* param next the next glyph in a string
* return advance width
*
*/
float Advance( unsigned int index, unsigned int next);
/**
* renders a character
*/
FT_Vector& render( unsigned int index, unsigned int next, FT_Vector pen);
private:
/**
*
*/
FT_Error err;
/**
*
*/
bool preCache;
/**
*
*/
int numGlyphs;
/**
*
*/
FTFace* face;
/**
*
*/
FT_Vector kernAdvance;
/**
*
*/
float advance;
/**
*
*/
vector<FTGlyph*> glyphs;
// typedef pair<int, FTGlyph*> CHARREF; // glyphIndex, glyph
// vector<CHARREF> glyphs;
// map< int, FTGlyph*> CHARREF; // charCode, glyph
};
#endif // __FTGlyphContainer__

65
src/osgText/FTLibrary.cc Normal file
View File

@ -0,0 +1,65 @@
#include "FTLibrary.h"
#include "FTGL.h"
FTLibrary& FTLibrary::Instance()
{
static FTLibrary ftlib;
return ftlib;
}
FTLibrary::~FTLibrary()
{
if( lib != 0)
{
FT_Done_FreeType( *lib);
delete lib;
lib= 0;
}
// if( manager != 0)
// {
// FTC_Manager_Done( manager );
//
// delete manager;
// manager= 0;
// }
}
FTLibrary::FTLibrary()
: lib(0),
err(0)
{
Init();
}
bool FTLibrary::Init()
{
if( lib != 0 )
return true;
lib = new FT_Library;
err = FT_Init_FreeType( lib);
if( err)
{
delete lib;
lib = 0;
return false;
}
// FTC_Manager* manager;
//
// if( FTC_Manager_New( lib, 0, 0, 0, my_face_requester, 0, manager )
// {
// delete manager;
// manager= 0;
// return false;
// }
return true;
}

102
src/osgText/FTLibrary.h Normal file
View File

@ -0,0 +1,102 @@
#ifndef __FTLibrary__
#define __FTLibrary__
#include <ft2build.h>
#include FT_FREETYPE_H
//#include FT_CACHE_H
#include "FTGL.h"
/**
* FTLibrary class is the global accessor for the Freetype library.
*
* This class encapsulates the Freetype Library. This is a singleton class
* and ensures that only one FT_Library is in existence at any one time.
* All constructors are private therefore clients cannot create or
* instantiate this class themselves and must access it's methods via the
* static <code>FTLibrary::Instance()</code> function.
*
* Just because this class returns a valid <code>FTLibrary</code> object
* doesn't mean that the Freetype Library has been successfully initialised.
* Clients should check for errors. You can initialse the library AND check
* for errors using the following code...
* <code>err = FTLibrary::Instance().Error();</code>
*
* @see "Freetype 2 Documentation - 2.0.4"
*
*/
class FTLibrary
{
public:
// methods
/**
* Global acces point to the single FTLibrary object.
*
* @return The global <code>FTLibrary</code> object.
*/
static FTLibrary& Instance();
/**
* Gets a pointer to the native Freetype library.
*
* @return A handle to a FreeType library instance.
*/
FT_Library* GetLibrary() const { return lib;}
/**
* Queries the library for errors.
*
* @return The current error code.
*/
virtual FT_Error Error() const { return err;}
/**
* Destructor
*
* Disposes of the Freetype library
*/
virtual ~FTLibrary();
// attributes
private:
// methods
/**
* Default constructors.
*
* Made private to stop clients creating there own FTLibrary
* objects.
*/
FTLibrary();
FTLibrary( const FT_Library&){}
FTLibrary& operator=( const FT_Library&){}
/**
* Initialises the Freetype library
*
* Even though this function indicates success via the return value,
* clients can't see this so must check the error codes.
*
* @return <code>true</code> if the Freetype library was
* successfully initialised, <code>false</code>
* otherwise.
*/
bool Init();
// attributes
/**
* Freetype library handle.
*/
FT_Library* lib;
// FTC_Manager* manager;
/**
* Current error code. Zero means no error.
*/
FT_Error err;
};
#endif // __FTLibrary__

View File

@ -0,0 +1,83 @@
#include "GL/gl.h"
#include "FTOutlineGlyph.h"
#include "FTVectoriser.h"
#include "FTGL.h"
FTOutlineGlyph::FTOutlineGlyph( FT_Glyph glyph)
: FTGlyph(),
vectoriser(0),
numPoints(0),
numContours(0),
contourLength(0),
data(0),
glList(0)
{
if( ft_glyph_format_outline != glyph->format)
{
return;
}
vectoriser = new FTVectoriser( glyph);
vectoriser->Ingest();
numContours = vectoriser->contours();
contourLength = new int[ numContours];
for( int cn = 0; cn < numContours; ++cn)
{
contourLength[cn] = vectoriser->contourSize( cn);
}
numPoints = vectoriser->points();
data = new double[ numPoints * 3];
vectoriser->Output( data);
advance = glyph->advance.x >> 16;
delete vectoriser;
if ( ( numContours < 1) || ( numPoints < 3))
return;
glList = glGenLists(1);
int d = 0;
glNewList( glList, GL_COMPILE);
for( int c = 0; c < numContours; ++c)
{
glBegin( GL_LINE_LOOP);
for( int p = 0; p < ( contourLength[c]); ++p)
{
glVertex2dv( data + d);
d += 3;
}
glEnd();
}
glEndList();
// discard glyph image (bitmap or not)
FT_Done_Glyph( glyph); // Why does this have to be HERE
}
FTOutlineGlyph::~FTOutlineGlyph()
{
delete [] data;
delete [] contourLength;
}
float FTOutlineGlyph::Render( const FT_Vector& pen)
{
if( glList)
{
glTranslatef( pen.x, pen.y, 0);
glCallList( glList);
glTranslatef( -pen.x, -pen.y, 0);
}
return advance;
}

View File

@ -0,0 +1,36 @@
#ifndef __FTOutlineGlyph__
#define __FTOutlineGlyph__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include "FTGlyph.h"
class FTVectoriser;
class FTOutlineGlyph : public FTGlyph
{
public:
// methods
FTOutlineGlyph( FT_Glyph glyph);
virtual ~FTOutlineGlyph();
virtual float Render( const FT_Vector& pen);
// attributes
private:
// methods
// attributes
FTVectoriser* vectoriser;
int numPoints;
int numContours;
int* contourLength;
double* data;
int glList;
};
#endif // __FTOutlineGlyph__

View File

@ -0,0 +1,94 @@
#include "GL/gl.h"
#include "FTPixmapGlyph.h"
#include "FTGL.h"
FTPixmapGlyph::FTPixmapGlyph( FT_Glyph glyph)
: FTGlyph(),
destWidth(0),
destHeight(0),
numGreys(0),
data(0)
{
// This function will always fail if the glyph's format isn't scalable????
FT_Error err = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1);
if( err || ft_glyph_format_bitmap != glyph->format)
{
return;
}
FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
FT_Bitmap* source = &bitmap->bitmap;
//check the pixel mode
//ft_pixel_mode_grays
int srcWidth = source->width;
int srcHeight = source->rows;
int srcPitch = source->pitch;
numGreys = source->num_grays;
advance = glyph->advance.x >> 16;
pos.x = bitmap->left;
pos.y = srcHeight - bitmap->top;
// FIXME What about dest alignment?
destWidth = srcWidth;
destHeight = srcHeight;
data = new unsigned char[destWidth * destHeight * 4];
// Get the current glColor.
float ftglColour[4];
glGetFloatv( GL_CURRENT_COLOR, ftglColour);
for(int y = 0; y < srcHeight; ++y)
{
--destHeight;
for(int x = 0; x < srcWidth; ++x)
{
*( data + ( destHeight * destWidth + x) * 4 + 0) = static_cast<unsigned char>( ftglColour[0] * 255.0f);
*( data + ( destHeight * destWidth + x) * 4 + 1) = static_cast<unsigned char>( ftglColour[1] * 255.0f);
*( data + ( destHeight * destWidth + x) * 4 + 2) = static_cast<unsigned char>( ftglColour[2] * 255.0f);
*( data + ( destHeight * destWidth + x) * 4 + 3) = static_cast<unsigned char>( ftglColour[3] * (*( source->buffer + ( y * srcPitch) + x)));
}
}
destHeight = srcHeight;
// discard glyph image (bitmap or not)
// Is this the right place to do this?
FT_Done_Glyph( glyph );
}
FTPixmapGlyph::~FTPixmapGlyph()
{
delete[] data;
}
float FTPixmapGlyph::Render( const FT_Vector& pen)
{
if( data != 0 )
{
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT);
// Move the glyph origin
glBitmap( 0, 0, 0.0, 0.0, pen.x + pos.x, pen.y - pos.y, (const GLubyte *)0);
glPixelStorei( GL_UNPACK_ROW_LENGTH, destWidth);
glDrawPixels( destWidth, destHeight, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)data);
// Restore the glyph origin
glBitmap( 0, 0, 0.0, 0.0, -pen.x - pos.x, -pen.y + pos.y, (const GLubyte *)0);
glPopClientAttrib();
}
return advance;
}

View File

@ -0,0 +1,35 @@
#ifndef __FTPixmapGlyph__
#define __FTPixmapGlyph__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include "FTGlyph.h"
class FTPixmapGlyph : public FTGlyph
{
public:
// methods
FTPixmapGlyph( FT_Glyph glyph);
virtual ~FTPixmapGlyph();
virtual float Render( const FT_Vector& pen);
// attributes
private:
// methods
// attributes
int destWidth;
int destHeight;
int numGreys;
unsigned char* data;
};
#endif // __FTPixmapGlyph__

156
src/osgText/FTPolyGlyph.cc Normal file
View File

@ -0,0 +1,156 @@
#include "GL/gl.h"
#include "GL/glu.h"
#include "FTPolyGlyph.h"
#include "FTVectoriser.h"
#include "FTGL.h"
#ifndef CALLBACK
#define CALLBACK
#endif
void CALLBACK ftglError( GLenum errCode)
{
// const GLubyte* estring;
// estring = gluErrorString( errCode);
// fprintf( stderr, "ERROR : %s\n", estring);
// exit(1);
}
void CALLBACK ftglVertex( void* data)
{
glVertex3dv( (double*)data);
}
void CALLBACK ftglBegin( GLenum type)
{
glBegin( type);
}
void CALLBACK ftglEnd()
{
glEnd();
}
void CALLBACK ftglCombine( GLdouble coords[3], void* vertex_data[4], GLfloat weight[4], void** outData)
{
double* vertex = new double[3]; // FIXME MEM LEAK
vertex[0] = coords[0];
vertex[1] = coords[1];
vertex[2] = coords[2];
*outData = vertex;
}
FTPolyGlyph::FTPolyGlyph( FT_Glyph glyph)
: FTGlyph(),
vectoriser(0),
numPoints(0),
numContours(0),
contourLength(0),
data(0),
glList(0)
{
if( ft_glyph_format_outline != glyph->format)
{ return;}
vectoriser = new FTVectoriser( glyph);
vectoriser->Ingest();
numContours = vectoriser->contours();
contourLength = new int[ numContours];
for( int c = 0; c < numContours; ++c)
{
contourLength[c] = vectoriser->contourSize( c);
}
numPoints = vectoriser->points();
data = new double[ numPoints * 3];
vectoriser->Output( data);
contourFlag = vectoriser->ContourFlag();
advance = glyph->advance.x >> 16;
delete vectoriser;
if ( ( numContours < 1) || ( numPoints < 3))
return;
Tesselate();
// discard glyph image (bitmap or not)
FT_Done_Glyph( glyph); // Why does this have to be HERE
}
void FTPolyGlyph::Tesselate()
{
glList = glGenLists(1);
GLUtesselator* tobj = gluNewTess();
int d = 0;
gluTessCallback( tobj, GLU_TESS_BEGIN, (void (CALLBACK*)())ftglBegin);
gluTessCallback( tobj, GLU_TESS_VERTEX, (void (CALLBACK*)())ftglVertex);
gluTessCallback( tobj, GLU_TESS_COMBINE, (void (CALLBACK*)())ftglCombine);
gluTessCallback( tobj, GLU_TESS_END, ftglEnd);
gluTessCallback( tobj, GLU_TESS_ERROR, (void (CALLBACK*)())ftglError);
glNewList( glList, GL_COMPILE);
if( contourFlag & ft_outline_even_odd_fill) // ft_outline_reverse_fill
{
gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
}
else
{
gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
}
gluTessProperty( tobj, GLU_TESS_TOLERANCE, 0);
gluTessBeginPolygon( tobj, NULL);
for( int c = 0; c < numContours; ++c)
{
gluTessBeginContour( tobj);
for( int p = 0; p < ( contourLength[c]); ++p)
{
gluTessVertex( tobj, data + d, data + d);
d += 3;
}
gluTessEndContour( tobj);
}
gluTessEndPolygon( tobj);
glEndList();
gluDeleteTess( tobj);
}
FTPolyGlyph::~FTPolyGlyph()
{
delete [] data;
delete [] contourLength;
}
float FTPolyGlyph::Render( const FT_Vector& pen)
{
if( glList)
{
glTranslatef( pen.x, pen.y, 0);
glCallList( glList);
glTranslatef( -pen.x, -pen.y, 0);
}
return advance;
}

38
src/osgText/FTPolyGlyph.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef __FTPolyGlyph__
#define __FTPolyGlyph__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include "FTGlyph.h"
class FTVectoriser;
class FTPolyGlyph : public FTGlyph
{
public:
// methods
FTPolyGlyph( FT_Glyph glyph);
virtual ~FTPolyGlyph();
virtual float Render( const FT_Vector& pen);
// attributes
private:
// methods
void Tesselate();
// attributes
FTVectoriser* vectoriser;
int numPoints;
int numContours;
int contourFlag;
int* contourLength;
double* data;
int glList;
};
#endif // __FTPolyGlyph__

91
src/osgText/FTSize.cc Normal file
View File

@ -0,0 +1,91 @@
#include "FTSize.h"
#include "FTGL.h"
FTSize::FTSize()
: size(0),
ftFace(0),
err(0)
{}
FTSize::~FTSize()
{}
bool FTSize::CharSize( FT_Face* face, unsigned int point_size, unsigned int x_resolution, unsigned int y_resolution )
{
ftFace = face;
size = point_size;
err = FT_Set_Char_Size( *ftFace, 0L, point_size * 64, x_resolution, y_resolution);
ftSize = (*ftFace)->size;
return !err;
}
int FTSize::Ascender() const
{
return ftSize->metrics.ascender >> 6;
}
int FTSize::Descender() const
{
return ftSize->metrics.descender >> 6;
}
int FTSize::Height() const
{
if( FT_IS_SCALABLE((*ftFace)))
{
float height;
if( FT_IS_SFNT((*ftFace))) // Don't think this is correct
{
height = (*ftFace)->bbox.yMax - (*ftFace)->bbox.yMin; // bbox.yMax-bbox.yMin
}
else
{
height = (*ftFace)->bbox.yMax - (*ftFace)->bbox.yMin >> 16; // bbox.yMax-bbox.yMin
}
height = height * ( (float)ftSize->metrics.y_ppem / (float)(*ftFace)->units_per_EM);
return static_cast<int>(height);
}
else
{
return ftSize->metrics.height >> 6;
}
}
int FTSize::Width() const
{
if( FT_IS_SCALABLE((*ftFace)))
{
float width;
if( FT_IS_SFNT((*ftFace))) // Don't think this is correct
{
width = ((*ftFace)->bbox.xMax - (*ftFace)->bbox.xMin); // bbox.xMax-bbox.xMin
}
else
{
width = ((*ftFace)->bbox.xMax - (*ftFace)->bbox.xMin) >> 16; // bbox.xMax-bbox.xMin
}
width = width * ( (float)ftSize->metrics.x_ppem / (float)(*ftFace)->units_per_EM);
return static_cast<int>(width);
}
else
{
return ftSize->metrics.max_advance >> 6;
}
}
int FTSize::Underline() const
{
return 0;
}

118
src/osgText/FTSize.h Normal file
View File

@ -0,0 +1,118 @@
#ifndef __FTSize__
#define __FTSize__
#include <ft2build.h>
#include FT_FREETYPE_H
#include "FTGL.h"
/**
* FTSize class provides an abstraction layer for the Freetype Size.
*
* @see "Freetype 2 Documentation - 2.0.4"
*
*/
class FTSize
{
public:
/**
* Default Constructor
*/
FTSize();
/**
* Destructor
*/
virtual ~FTSize();
/**
* Sets the char size for the current face.
*
* This doesn't guarantee that the size was set correctly. Clients
* should check errors.
*
* @param point_size the face size in points (1/72 inch)
* @param x_resolution the horizontal resolution of the target device.
* @param y_resolution the vertical resolution of the target device.
* @return <code>true</code> if the size has been set. Clients should check Error() for more information if this function returns false()
*/
bool CharSize( FT_Face* face, unsigned int point_size, unsigned int x_resolution, unsigned int y_resolution );
/**
* Gets the global ascender height for the face in pixels.
*
* @return Ascender height
*/
int Ascender() const;
/**
* Gets the global descender height for the face in pixels.
*
* @return Ascender height
*/
int Descender() const;
/**
* Gets the global face height for the face.
*
* If the face is scalable this returns the height of the global
* bounding box which ensures that any glyph will be less than or
* equal to this height. If the font isn't scalable there is no
* guarantee that glyphs will not be taller than this value.
*
* @return height in pixels.
*/
int Height() const;
/**
* Gets the global face width for the face.
*
* If the face is scalable this returns the width of the global
* bounding box which ensures that any glyph will be less than or
* equal to this width. If the font isn't scalable this value is
* the max_advance for the face.
*
* @return width in pixels.
*/
int Width() const;
/**
* Gets the underline position for the face.
*
* @return underline position in pixels
*/
int Underline() const;
/**
* Queries for errors.
*
* @return The current error code.
*/
FT_Error Error() const { return err; }
private:
/**
* The current Freetype face that this FTSize object relates to.
*/
FT_Face* ftFace;
/**
* The Freetype size.
*/
FT_Size ftSize;
/**
* The size in points.
*/
unsigned int size;
/**
* Current error code. Zero means no error.
*/
FT_Error err;
};
#endif // __FTSize__

View File

@ -0,0 +1,92 @@
#include "GL/gl.h"
#include "FTTextureGlyph.h"
#include "FTGL.h"
int FTTextureGlyph::activeTextureID = 0;
FTTextureGlyph::FTTextureGlyph( FT_Glyph glyph, int id, unsigned char* data, int stride, int height, float u, float v)
: FTGlyph(),
destWidth(0),
destHeight(0),
numGreys(0),
glTextureID(id)
{
// This function will always fail if the glyph's format isn't scalable????
err = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1);
if( err || glyph->format != ft_glyph_format_bitmap)
{
return;
}
FT_BitmapGlyph bitmap = ( FT_BitmapGlyph)glyph;
FT_Bitmap* source = &bitmap->bitmap;
//check the pixel mode
//ft_pixel_mode_grays
int srcWidth = source->width;
int srcHeight = source->rows;
int srcPitch = source->pitch;
numGreys = source->num_grays;
advance = glyph->advance.x >> 16;
pos.x = bitmap->left;
pos.y = bitmap->top;
destWidth = srcWidth;
destHeight = srcHeight;
for(int y = 0; y < srcHeight; ++y)
{
for(int x = 0; x < srcWidth; ++x)
{
*( data + ( y * stride + x)) = *( source->buffer + ( y * srcPitch) + x);
}
}
// 0
// +----+
// | |
// | |
// | |
// +----+
// 1
uv[0].x = u;
uv[0].y = v;
uv[1].x = uv[0].x + ( (float)destWidth / (float)stride);
uv[1].y = uv[0].y + ( (float)destHeight / (float)height);
// discard glyph image (bitmap or not)
// Is this the right place to do this?
FT_Done_Glyph( glyph);
}
FTTextureGlyph::~FTTextureGlyph()
{
}
float FTTextureGlyph::Render( const FT_Vector& pen)
{
// This could be really ugly!!
if( activeTextureID != glTextureID)
{
glEnd();
glBindTexture( GL_TEXTURE_2D, (GLuint)glTextureID);
activeTextureID = glTextureID;
glBegin( GL_QUADS);
}
glTexCoord2f( uv[0].x, uv[0].y); glVertex2f( pen.x + pos.x, pen.y + pos.y);
glTexCoord2f( uv[1].x, uv[0].y); glVertex2f( pen.x + destWidth + pos.x, pen.y + pos.y);
glTexCoord2f( uv[1].x, uv[1].y); glVertex2f( pen.x + destWidth + pos.x, pen.y + pos.y - destHeight);
glTexCoord2f( uv[0].x, uv[1].y); glVertex2f( pen.x + pos.x, pen.y + pos.y - destHeight);
return advance;
}

View File

@ -0,0 +1,40 @@
#ifndef __FTTextureGlyph__
#define __FTTextureGlyph__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include "FTGlyph.h"
class FTTextureGlyph : public FTGlyph
{
public:
// methods
FTTextureGlyph( FT_Glyph glyph, int id, unsigned char* data, int stride, int height, float u, float v);
virtual ~FTTextureGlyph();
virtual float Render( const FT_Vector& pen);
static int activeTextureID;
private:
// attributes
// What about the other point class in vectoriser?
struct FTPoint
{
float x;
float y;
};
int destWidth;
int destHeight;
int numGreys;
FTPoint uv[2];
int glTextureID;
};
#endif // __FTTextureGlyph__

227
src/osgText/FTVectoriser.cc Normal file
View File

@ -0,0 +1,227 @@
#include "FTVectoriser.h"
#include "FTGL.h"
FTContour::FTContour()
: kMAXPOINTS( 1000)
{
pointList.reserve( kMAXPOINTS);
}
FTContour::~FTContour()
{
pointList.clear();
}
void FTContour::AddPoint( const float x, const float y)
{
ftPoint point( x, y, 0.0);
// Eliminate duplicate points.
if( pointList.empty() || ( pointList[pointList.size() - 1] != point && pointList[0] != point))
{
pointList.push_back( point);
}
}
FTVectoriser::FTVectoriser( const FT_Glyph glyph)
: contourFlag(0),
contour(0),
kBSTEPSIZE( 0.2)
{
FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph;
ftOutline = outline->outline;
contourList.reserve( ftOutline.n_contours);
}
FTVectoriser::~FTVectoriser()
{
for( int c = 0; c < contours(); ++c)
{
delete contourList[c];
}
contourList.clear();
}
int FTVectoriser::points()
{
int s = 0;
for( int c = 0; c < contours(); ++c)
{
s += contourList[c]->size();
}
return s;
}
bool FTVectoriser::Ingest()
{
short first = 0;
short last;
const short cont = ftOutline.n_contours;
for( short c = 0; c < cont; ++c)
{
contour = new FTContour;
contourFlag = ftOutline.flags;
last = ftOutline.contours[c];
for( short p = first; p <= last; ++p)
{
switch( ftOutline.tags[p])
{
case FT_Curve_Tag_Conic:
p += Conic( p, first, last);
break;
case FT_Curve_Tag_Cubic:
p += Cubic( p, first, last);
break;
case FT_Curve_Tag_On:
default:
contour->AddPoint( ftOutline.points[p].x, ftOutline.points[p].y);
}
}
contourList.push_back( contour);
first = last + 1;
}
return true;
}
int FTVectoriser::Conic( const int index, const int first, const int last)
{
int next = index + 1;
int prev = index - 1;
if( index == last)
next = first;
if( index == first)
prev = last;
if( ftOutline.tags[next] != FT_Curve_Tag_Conic)
{
ctrlPtArray[0][0] = ftOutline.points[prev].x; ctrlPtArray[0][1] = ftOutline.points[prev].y;
ctrlPtArray[1][0] = ftOutline.points[index].x; ctrlPtArray[1][1] = ftOutline.points[index].y;
ctrlPtArray[2][0] = ftOutline.points[next].x; ctrlPtArray[2][1] = ftOutline.points[next].y;
evaluateCurve( 2);
return 1;
}
else
{
int next2 = next + 1;
if( next == last)
next2 = first;
//create a phantom point
float x = ( ftOutline.points[index].x + ftOutline.points[next].x) / 2;
float y = ( ftOutline.points[index].y + ftOutline.points[next].y) / 2;
// process first curve
ctrlPtArray[0][0] = ftOutline.points[prev].x; ctrlPtArray[0][1] = ftOutline.points[prev].y;
ctrlPtArray[1][0] = ftOutline.points[index].x; ctrlPtArray[1][1] = ftOutline.points[index].y;
ctrlPtArray[2][0] = x; ctrlPtArray[2][1] = y;
evaluateCurve( 2);
// process second curve
ctrlPtArray[0][0] = x; ctrlPtArray[0][1] = y;
ctrlPtArray[1][0] = ftOutline.points[next].x; ctrlPtArray[1][1] = ftOutline.points[next].y;
ctrlPtArray[2][0] = ftOutline.points[next2].x; ctrlPtArray[2][1] = ftOutline.points[next2].y;
evaluateCurve( 2);
return 2;
}
}
int FTVectoriser::Cubic( const int index, const int first, const int last)
{
int next = index + 1;
int prev = index - 1;
if( index == last)
next = first;
int next2 = next + 1;
if( next == last)
next2 = first;
if( index == first)
prev = last;
ctrlPtArray[0][0] = ftOutline.points[prev].x; ctrlPtArray[0][1] = ftOutline.points[prev].y;
ctrlPtArray[1][0] = ftOutline.points[index].x; ctrlPtArray[1][1] = ftOutline.points[index].y;
ctrlPtArray[2][0] = ftOutline.points[next].x; ctrlPtArray[2][1] = ftOutline.points[next].y;
ctrlPtArray[3][0] = ftOutline.points[next2].x; ctrlPtArray[3][1] = ftOutline.points[next2].y;
evaluateCurve( 3);
return 2;
}
// De Casteljau algorithm contributed by Jed Soane
void FTVectoriser::deCasteljau( const float t, const int n)
{
//Calculating successive b(i)'s using de Casteljau algorithm.
for( int i = 1; i <= n; i++)
for( int k = 0; k <= (n - i); k++)
{
bValues[i][k][0] = (1 - t) * bValues[i - 1][k][0] + t * bValues[i - 1][k + 1][0];
bValues[i][k][1] = (1 - t) * bValues[i - 1][k][1] + t * bValues[i - 1][k + 1][1];
}
//Specify next vertex to be included on curve
contour->AddPoint( bValues[n][0][0], bValues[n][0][1]);
}
// De Casteljau algorithm contributed by Jed Soane
void FTVectoriser::evaluateCurve( const int n)
{
// setting the b(0) equal to the control points
for( int i = 0; i <= n; i++)
{
bValues[0][i][0] = ctrlPtArray[i][0];
bValues[0][i][1] = ctrlPtArray[i][1];
}
float t; //parameter for curve point calc. [0.0, 1.0]
for( int m = 0; m <= ( 1 / kBSTEPSIZE); m++)
{
t = m * kBSTEPSIZE;
deCasteljau( t, n); //calls to evaluate point on curve att.
}
}
void FTVectoriser::Output( double* data)
{
int i = 0;
for( int c= 0; c < contours(); ++c)
{
const FTContour* contour = contourList[c];
for( int p = 0; p < contour->size(); ++p)
{
data[i] = static_cast<double>(contour->pointList[p].x / 64.0f); // is 64 correct?
data[i + 1] = static_cast<double>(contour->pointList[p].y / 64.0f);
data[i + 2] = 0.0; // static_cast<double>(contour->pointList[p].z / 64.0f);
i += 3;
}
}
}

104
src/osgText/FTVectoriser.h Normal file
View File

@ -0,0 +1,104 @@
#ifndef __FTVectoriser__
#define __FTVectoriser__
#include <vector>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include "FTGlyph.h"
using namespace std;
class ftPoint
{
public:
ftPoint()
: x(0), y(0), z(0)
{}
ftPoint( const float X, const float Y, const float Z)
: x(X), y(Y), z(Z)
{}
friend bool operator == ( const ftPoint &a, const ftPoint &b)
{
return((a.x == b.x) && (a.y == b.y) && (a.z == b.z));
}
friend bool operator != ( const ftPoint &a, const ftPoint &b)
{
return((a.x != b.x) || (a.y != b.y) || (a.z != b.z));
}
float x, y, z; // FIXME make private
private:
};
class FTContour
{
public:
// methods
FTContour();
~FTContour();
void AddPoint( const float x, const float y);
int size() const { return pointList.size();}
// attributes
vector< ftPoint> pointList;
float ctrlPtArray[4][2];
private:
// methods
// attributes
const unsigned int kMAXPOINTS;
};
class FTVectoriser
{
public:
// methods
FTVectoriser( FT_Glyph glyph);
virtual ~FTVectoriser();
bool Ingest();
void Output( double* d);
int points();
int contours() const { return contourList.size();}
int contourSize( int c) const { return contourList[c]->size();}
int ContourFlag() const { return contourFlag;}
// attributes
private:
// methods
int Conic( const int index, const int first, const int last);
int Cubic( const int index, const int first, const int last);
void deCasteljau( const float t, const int n);
void evaluateCurve( const int n);
// attributes
vector< const FTContour*> contourList;
FTContour* contour;
int contourFlag;
FT_Outline ftOutline;
// Magic numbers -- #define MAX_DEG 4
float bValues[4][4][2]; //3D array storing values of de Casteljau algorithm.
float ctrlPtArray[4][2]; // Magic numbers
const float kBSTEPSIZE;
};
#endif // __FTVectoriser__

29
src/osgText/Makefile Normal file
View File

@ -0,0 +1,29 @@
#!smake
include ../../Make/makedefs
C++FILES = \
GLUTEventAdapter.cpp\
Version.cpp\
Window.cpp\
Viewer.cpp\
TARGET_BASENAME = osgGLUT
LIBS = -L../../lib -losgDB -losgUtil -losg $(GLUTLIB) -lGLU -lGL -lm
LIB = ../../lib/lib$(TARGET_BASENAME).so
#LIB = ../../lib/lib$(TARGET_BASENAME).a
TARGET_LIB_FILES = lib$(TARGET_BASENAME).so
TARGET_INCLUDE_FILES = \
osgGLUT/Export\
osgGLUT/GLUTEventAdapter\
osgGLUT/Version\
osgGLUT/Window\
osgGLUT/Viewer\
C++FLAGS += -I ../../include
include ../../Make/makerules

665
src/osgText/Text.cpp Normal file
View File

@ -0,0 +1,665 @@
/* --------------------------------------------------------------------------
*
* openscenegraph textLib / FTGL
*
* --------------------------------------------------------------------------
*
* prog: max rheiner;mrn@paus.ch
* date: 4/25/2001 (m/d/y)
*
* ----------------------------------------------------------------------------
*
* --------------------------------------------------------------------------
*/
#include <osgText/Text.h>
using namespace osgText;
///////////////////////////////////////////////////////////////////////////////
// Font
Font::
Font()
{
_init=false;
_font=NULL;
_created=false;
_pointSize=14;
_res=72;
}
bool Font::
init(const std::string& font)
{
_font=NULL;
_created=false;
open(font);
if(_font!=NULL)
return true;
else
return false;
}
Font::
~Font()
{
clear();
}
bool Font::
open(const std::string& font)
{
clear();
_font=createFontObj();
if( _font!=NULL && _font->Open(font.c_str()) )
{
_init=true;
_fontName=font;
return true;
}
else
return false;
}
bool Font::
create(int pointSize,const unsigned int res)
{
_pointSize=pointSize;
_res=res;
return create();
}
bool Font::
create()
{
if(_init)
{
if(_font->FaceSize(_pointSize,_res))
{
_created=true;
return true;
}
else
return false;
}
else
return false;
}
void Font::
output(const char* text)
{
if(_created)
_font->render(text);
else
create(_pointSize);
}
void Font::
clear()
{
_init=false;
if(_font)
{
delete _font;
_font=NULL;
}
_fontName="";
}
float Font::
getWidth(const char* text) const
{
if(_init && _created)
return _font->Advance(text);
else
return -1;
}
int Font::
getHeight() const
{
if(_init && _created)
return _pointSize;
else
return -1;
}
int Font::
getDescender() const
{
if(_init && _created)
return _font->Descender();
else
return -1;
}
int Font::
getAscender() const
{
if(_init && _created)
return _font->Ascender();
else
return -1;
}
// Font
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// BitmapFont
BitmapFont::
BitmapFont(const std::string& font,
int point_size):
RasterFont()
{
if(init(font))
{
}
_pointSize=point_size;
}
FTFont* BitmapFont::
createFontObj(void)
{
return (FTFont*)(new FTGLBitmapFont);
}
// BitmapFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// PixmapFont
PixmapFont::
PixmapFont(const std::string& font,
int point_size):
RasterFont(font)
{
if(init(font))
{
}
_pointSize=point_size;
}
FTFont* PixmapFont::
createFontObj(void)
{
return (FTFont*)(new FTGLPixmapFont);
}
// PixmapFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// PixmapFont
TextureFont::
TextureFont(const std::string& font,
int point_size):
RasterFont(font)
{
if(init(font))
{
}
_pointSize=point_size;
}
FTFont* TextureFont::
createFontObj(void)
{
return (FTFont*)(new FTGLTextureFont);
}
// PixmapFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// _FTGLOutlineFont
OutlineFont::
OutlineFont(const std::string& font,
int point_size,
double precision):
VectorFont(font)
{
if(init(font))
{
}
_pointSize=point_size;
_precision=precision;
}
FTFont* OutlineFont::
createFontObj(void)
{
return (FTFont*)(new FTGLOutlineFont);
}
// _FTGLOutlineFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// PolygonFont
PolygonFont::
PolygonFont(const std::string& font,
int point_size,
double precision):
VectorFont(font)
{
if(init(font))
{
}
_pointSize=point_size;
_precision=precision;
}
FTFont* PolygonFont::
createFontObj(void)
{
return (FTFont*)(new FTGLPolygonFont);
}
// PolygonFont
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Text
Text::
Text()
{
setDefaults();
}
Text::
Text(Font* font)
{
setDefaults();
if(font && font->isOk())
{
_init=true;
_font=font;
if(dynamic_cast<PolygonFont*>(_font.get()))
_fontType=POLYGON;
else if(dynamic_cast<BitmapFont*>(_font.get()))
_fontType=BITMAP;
else if(dynamic_cast<PixmapFont*>(_font.get()))
_fontType=PIXMAP;
else if(dynamic_cast<TextureFont*>(_font.get()))
_fontType=TEXTURE;
else if(dynamic_cast<OutlineFont*>(_font.get()))
_fontType=OUTLINE;
}
}
Text::
~Text()
{
}
void Text::
setDefaults()
{
_init=false;
_pos.set(0,0,0);
_alignementPos.set(0,0,0);
_fontType=UNDEF;
_alignement=LEFT_BOTTOM;
_drawMode=DrawModeType::DEFAULT;
_boundingBoxType=GLYPH;
_boundingBoxType=GEOMETRY;
_initAlignement=false;
_useDisplayList=false;
}
const bool Text::
computeBound() const
{
if(!_init)
{
_bbox_computed=false;
return true;
}
// culling
if(_font->isCreated())
{ // ready to get the siz
_bbox.init();
Vec3 min,max;
calcBounds(&min,&max);
_bbox.expandBy(min);
_bbox.expandBy(max);
_bbox_computed=true;
}
else
{ // have to wait for the init.
_bbox.init();
// to be sure that the obj isn't culled
_bbox.expandBy(_pos + Vec3(-100,-100,-100));
_bbox.expandBy(_pos + Vec3(100,100,100));
/*
_bbox.expandBy(Vec3(-FLT_MAX,-FLT_MAX,-FLT_MAX));
_bbox.expandBy(Vec3(FLT_MAX,FLT_MAX,FLT_MAX));
*/
_bbox_computed=true;
}
return true;
}
void Text::
drawImmediateMode(State& state)
{
if(!_init)
return;
if(!_font->isCreated())
{
_font->create();
dirtyBound();
}
if(!_initAlignement)
initAlignement();
// draw boundingBox
if(_drawMode & BOUNDINGBOX)
drawBoundingBox();
// draw alignement
if(_drawMode & ALIGNEMENT)
drawAlignement();
// draw boundingBox
if(_drawMode & TEXT)
{
Vec3 drawPos(_pos+_alignementPos);
glPushMatrix();
switch(_fontType)
{
case POLYGON:
glTranslatef(drawPos.x(),drawPos.y(),drawPos.z());
_font->output(_text.c_str());
break;
case OUTLINE:
glTranslatef(drawPos.x(),drawPos.y(),drawPos.z());
_font->output(_text.c_str());
break;
case BITMAP:
glRasterPos3f(drawPos.x(),drawPos.y(),drawPos.z());
_font->output(_text.c_str());
break;
case PIXMAP:
glRasterPos3f(drawPos.x(),drawPos.y(),drawPos.z());
_font->output(_text.c_str());
break;
case TEXTURE:
glTranslatef(drawPos.x(),drawPos.y(),drawPos.z());
_font->output(_text.c_str());
break;
};
glPopMatrix();
}
}
void Text::
drawBoundingBox(void)
{
if(!_init)
return;
glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT );
glDisable(GL_TEXTURE_2D);
glColor3f(0,1,0);
glBegin(GL_LINE_LOOP);
glVertex3f(_bbox.xMin(),_bbox.yMin(),_bbox.zMin());
glVertex3f(_bbox.xMax(),_bbox.yMin(),_bbox.zMin());
glVertex3f(_bbox.xMax(),_bbox.yMax(),_bbox.zMin());
glVertex3f(_bbox.xMin(),_bbox.yMax(),_bbox.zMin());
glEnd();
glPopAttrib();
}
void Text::
drawAlignement(void)
{
if(!_init)
return;
double size=_font->getPointSize()/4;
glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT );
glDisable(GL_TEXTURE_2D);
glColor3f(1,0,0);
glBegin(GL_LINES);
glVertex3f(_pos.x() - size,_pos.y(),_pos.z());
glVertex3f(_pos.x() + size,_pos.y(),_pos.z());
glVertex3f(_pos.x(),_pos.y() - size,_pos.z());
glVertex3f(_pos.x(),_pos.y() + size,_pos.z());
glEnd();
glPopAttrib();
}
void Text::
setPosition(const Vec3& pos)
{
_pos=pos;
}
void Text::
setPosition(const Vec2& pos)
{
setPosition(Vec3(pos.x(),pos.y(),0));
}
void Text::
calcBounds(Vec3* min,Vec3* max) const
{
if(!_init)
return;
int h=_font->getHeight();
int w=_font->getWidth(_text.c_str());
int descender=_font->getDescender();
min->set(0,descender,0);
max->set(w,h + descender ,0);
}
bool Text::
initAlignement(void)
{
if(!_init)
return false;
// culling
if(_font->isCreated())
{ // ready to get the siz
_bbox.init();
Vec3 min,max;
initAlignement(&min,&max);
_bbox.expandBy(min);
_bbox.expandBy(max);
_bbox_computed=true;
_initAlignement=true;
}
else
{ // have to wait for the init.
_bbox.init();
// to be sure that the obj isn't culled
_bbox.expandBy(Vec3(-FLT_MAX,-FLT_MAX,-FLT_MAX));
_bbox.expandBy(Vec3(FLT_MAX,FLT_MAX,FLT_MAX));
_bbox_computed=true;
}
return true;
}
void Text::
initAlignement(Vec3* min,Vec3* max)
{
if(!_init)
return;
int h=_font->getHeight();
int w=_font->getWidth(_text.c_str());
int descender=_font->getDescender();
min->set(0,descender,0);
max->set(w,h + descender ,0);
switch(_boundingBoxType)
{
case GLYPH:
h+=descender;
switch(_alignement)
{
case LEFT_TOP:
_alignementPos.set(0,h,0);
break;
case LEFT_CENTER:
_alignementPos.set(0,h/2,0);
break;
case LEFT_BOTTOM:
_alignementPos.set(0,0,0);
break;
case CENTER_TOP:
_alignementPos.set(w/2,h,0);
break;
case CENTER_CENTER:
_alignementPos.set(w/2,h/2,0);
break;
case CENTER_BOTTOM:
_alignementPos.set(w/2,0,0);
break;
case RIGHT_TOP:
_alignementPos.set(w,h,0);
break;
case RIGHT_CENTER:
_alignementPos.set(w,h/2,0);
break;
case RIGHT_BOTTOM:
_alignementPos.set(w,0,0);
break;
};
_alignementPos=-_alignementPos;
*min+=_pos+_alignementPos;
*max+=_pos+_alignementPos;
break;
case GEOMETRY:
switch(_alignement)
{
case LEFT_TOP:
_alignementPos.set(0,h + descender,0);
break;
case LEFT_CENTER:
_alignementPos.set(0,(max->y()-min->y()) /2 + descender,0);
break;
case LEFT_BOTTOM:
_alignementPos.set(0,descender,0);
break;
case CENTER_TOP:
_alignementPos.set(w/2,h + descender,0);
break;
case CENTER_CENTER:
_alignementPos.set(w/2,(max->y()-min->y()) /2 + descender,0);
break;
case CENTER_BOTTOM:
_alignementPos.set(w/2,descender,0);
break;
case RIGHT_TOP:
_alignementPos.set(w,h + descender,0);
break;
case RIGHT_CENTER:
_alignementPos.set(w,(max->y()-min->y()) /2 + descender,0);
break;
case RIGHT_BOTTOM:
_alignementPos.set(w,descender,0);
break;
};
_alignementPos=-_alignementPos;
*min+=_pos+_alignementPos;
*max+=_pos+_alignementPos;
break;
};
switch(_fontType)
{
case BITMAP:
break;
case PIXMAP:
break;
};
}
void Text::
setAlignement(int alignement)
{
_alignement=alignement;
if(!_init || !_font->isCreated())
return;
initAlignement();
}
void Text::
setBoundingBox(int mode)
{
_boundingBoxType=mode;
if(!_init || !_font->isCreated())
return;
initAlignement();
}
// Text
///////////////////////////////////////////////////////////////////////////////