Files
OpenSceneGraph/src/osgText/FTPolyGlyph.cpp
Robert Osfield 00cc3a1833 Converted the instance of osgNew and osgDelete back to new and delete as part
of depecating the include/osg/MemoryManager
2002-12-16 13:40:58 +00:00

186 lines
4.2 KiB
C++

#include "FTPolyGlyph.h"
#include "FTVectoriser.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();
}
// this static vector is to keep track of memory allocated by the combine
// callback below, so that it can be later deleted. This approach does
// assume that the Tesselate method is single threaded.
typedef std::vector<double*> CreatedVertices;
static CreatedVertices s_createdVertices;
void CALLBACK ftglCombine( GLdouble coords[3], void* /*vertex_data*/[4], GLfloat /*weight*/[4], void** outData)
{
double* vertex = new double[3]; // FIXME MEM LEAK
s_createdVertices.push_back(vertex);
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),
contourFlag(0),
contourLength(0),
data(0),
glList(0)
{
if( ft_glyph_format_outline != glyph->format)
{
FT_Done_Glyph( glyph );
return;
}
advance = glyph->advance.x >> 16;
vectoriser = new FTVectoriser( glyph);
vectoriser->Process();
numContours = vectoriser->contours();
if (numContours==0) return;
contourLength = new int[ numContours];
memset(contourLength,0,sizeof(int)*numContours);
for( int c = 0; c < numContours; ++c)
{
contourLength[c] = vectoriser->contourSize( c);
}
numPoints = vectoriser->points();
data = new double[ numPoints * 3];
// initalize memory.
for( int pc=0;pc<numPoints*3;++pc) data[pc]=0.0;
// FIXME MakeMesh
vectoriser->MakeOutline( data);
contourFlag = vectoriser->ContourFlag();
vectoriser=0; // delete it, using ref_ptr.
if ( ( numContours < 1) || ( numPoints < 3))
{
FT_Done_Glyph( glyph );
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);
// clean up the vertices create in the combine callback.
for(CreatedVertices::iterator itr=s_createdVertices.begin();
itr!=s_createdVertices.end();
++itr)
{
delete [] (*itr);
}
s_createdVertices.clear();
}
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;
}