//---------------------------------------------------------------------------------
//	strokeChars()
//---------------------------------------------------------------------------------
bool FontMaker::strokeChars()
{
	bool result = true;
	// stroke chars and get some metrics
	
	FT_Glyph glyph;
	CharInfo* ci = 0;
	_lineHeight = 0;
//	int maxYOffset = 0;
//	int minYOffset = 100500;

	
	// Set up a stroker.
	FT_Stroker stroker;
	FT_Stroker_New( _library, &stroker );
	FT_Stroker_Set( stroker,
				   (int)( _outlineWidth * 64 ),
				   FT_STROKER_LINECAP_ROUND,
				   FT_STROKER_LINEJOIN_ROUND,
				   0 );
	
	set<FT_UInt> missing;
	
	for( CharSetIt it = _charSet.begin(); it != _charSet.end(); it++ )
	{
		ci = &(*it).second;
		
		ci->bodySpans.clear();
		ci->outlineSpans.clear();
		
		
		FT_UInt glyph_index = FT_Get_Char_Index( _face, ci->charcode );
		
		if( glyph_index == 0 )
		{
			result = false;
			printf( "WARNING: no glyph for charcode 0x%X\n", ci->charcode );
			missing.insert( ci->charcode );
		}
		
		FT_Load_Glyph( _face, glyph_index, FT_LOAD_DEFAULT );
		FT_Get_Glyph( _face->glyph, &ci->glyph );
		
		ci->xoffset = _face->glyph->metrics.horiBearingX / 64 - _outlineWidth;// - _padding;
		ci->yoffset = ( _face->size->metrics.ascender - _face->glyph->metrics.horiBearingY ) / 64;
		
		ci->xadvance = _face->glyph->metrics.horiAdvance / 64;

		
		if( _flags & DRAW_OUTLINE )
		{
			FT_Glyph_Copy( ci->glyph, &glyph );
			
			if( glyph->format == FT_GLYPH_FORMAT_OUTLINE )
			{
				
				FT_Glyph_StrokeBorder( &glyph, stroker, 0, 1 );
				
				// Render the outline spans to the span list
				
				FT_Outline *outline = &reinterpret_cast<FT_OutlineGlyph>(glyph)->outline;
				FT_Raster_Params params;
				memset( &params, 0, sizeof( params ) );
				params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT;
				params.gray_spans = renderCallback;
				params.user = &ci->outlineSpans;
				
				FT_Outline_Render( _library, outline, &params );
			}
			
			
			FT_Done_Glyph( glyph );
		}
		
//		if( _flags & DRAW_BODY ) // draw this always
		{
			FT_Glyph_Copy( ci->glyph, &glyph );
			
			FT_Outline *outline = &reinterpret_cast<FT_OutlineGlyph>(glyph)->outline;
			FT_Raster_Params params;
			memset( &params, 0, sizeof( params ) );
			params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT;
			params.gray_spans = renderCallback;
			params.user = &ci->bodySpans;
			
			FT_Outline_Render( _library, outline, &params );
			
			
			FT_Done_Glyph( glyph );
		}
		
//		ci->updateMetrics( _padding );
		
		if( _lineHeight < ci->height )
			_lineHeight = ci->height;

//		if( maxYOffset < ci->yoffset )
//			maxYOffset = ci->yoffset;
//
//		if( minYOffset > ci->yoffset )
//			minYOffset = ci->yoffset;

		ci->updateMetrics( _padding );
	}
	
	if( _removeMissing )
	{
		for( set<FT_UInt>::iterator it = missing.begin(); it != missing.end(); it++ )
		{
			_charSet.erase( *it );
		}
	}
	
	// update yoffset for all
//	maxYOffset = ( _face->size->metrics.ascender + _face->size->metrics.descender ) / 64;
//	maxYOffset += _face->size->metrics.descender / 64;
//	for( CharSetIt it = _charSet.begin(); it != _charSet.end(); it++ )
//	{
//		it->second.yoffset = maxYOffset - it->second.yoffset + minYOffset;
//	}

	FT_Stroker_Done( stroker );
	
	return result;
}