Results 1 to 10 of 10

Thread: About Text rendering

  1. #1
    Junior Member
    Join Date
    Feb 2009
    Posts
    6

    About Text rendering

    According to the specifiction v 1.1, Glyphs in OpenVG can be represented either using VGPath or VGImage data.

    However, I think, before assigning the given path to a glyph, we have to put some information such as vertex and edges on a path or an Image.

    If so, how can I map the given characters to a glyph or path with a font type such as truetype and opentype..

    In the Spec, I can't figure it out.~~

    Please help me.~~

  2. #2
    Senior Member
    Join Date
    Feb 2006
    Posts
    115

    Re: About Text rendering

    It's simple.
    - Create the path like normal populating then the right path data.
    - Create a Font object
    - Bind the indivual paths to the font object
    - Destroy the paths (recommended to do this now by the spec - can be done later)
    To render:
    - Set up your origin and glyph transformations
    - Render with vgDrawGlyph() or vgDrawGlyphs()
    To Clean up:
    - Destory the font

    For example:

    Code :
        VGFont  font;
        VGPath  fontpath1;
        VGImage fontimg1;
     
        font        = vgCreateFont(0);
        fontpath1   = vgCreatePath(VG_PATH_FORMAT_STANDARD,VG_PATH_DATATYPE_F, 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
        fontimg1    = vgCreateImage( VG_sRGBA_8888, IMAGE_WIDTH, IMAGE_HEIGHT, VG_IMAGE_QUALITY_FASTER );
     
        vguEllipse(fontpath1, 5.0f,5.0f,5.0f,5.0f);
        vgImageSubData( fontimg1, image_data, IMAGE_WIDTH*4, VG_sRGBA_8888, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT );
     
        vgSetGlyphToPath(font, 'a',fontpath1, 1, origin, escapement);
        vgDestroyPath(fontpath1);
        vgSetGlyphToImage(font, 'b',fontimg1, origin, escapement);
     
    ...
        // then to draw
        float origin[2];
        vgSetfv(VG_GLYPH_ORIGIN, 2, origin);
        vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);
        vgLoadIdentity();
     
        vgDrawGlyph(font, 'a', VG_FILL_PATH, 1);
        {
            int glyphs[] = {'b','a','d'};
            vgDrawGlyphs(font, 3, glyphs, NULL, NULL, VG_FILL_PATH, 1);
        }

  3. #3
    Junior Member
    Join Date
    Feb 2009
    Posts
    6

    Re: About Text rendering

    Thank you for giving me the example~
    However I could not run the code.

    When I ran the example with your code, I just saw the ellipse without font.

    First, I can not understand what the fontimg1 should have to have with image_data. I would like to know the data of image_data.

    Second, because I don't know the relationship between image_data and font, I just leave the all of the image part out from the code, then I could see just one ellipse.

    I think I need something more information about it with RI(reference implementation) 1.1.

  4. #4
    Senior Member
    Join Date
    Feb 2006
    Posts
    115

    Re: About Text rendering

    I didn't include the image data in the snippet - it can be any image data you want.

    If you saw the ellipse, then you saw exactly what you were supposed to see. In this font, the ellipse path is associated with the
    letter 'a' - and you asked it to print the letter 'a'.

    Remember, vguEllipse() can be substituded by vgAppendPathData() to use any path data you want.
    Similarly, any number of characters may be added to the font with vgSetGlyphToPath() - meaning you can associate path1 with 'a', path2 to 'b', etc.

  5. #5
    Junior Member
    Join Date
    Feb 2009
    Posts
    6

    Re: About Text rendering

    Thank you so much replying to my question....

    Acutally I couldn't understand what the concept of VGFont in OpenVG is..... because I always wanted to see really 'a' or 'b' on the screen not the index..

    If so, do you have any example font paths or images..

    If you have, please let me have it from you... if not, please let me know How I can use Windows Font such as True Type Font..

    I read the specifiction of TTF, then I knew it also consisted of several paths. So, please let me see real character on my screen.

  6. #6

    Re: About Text rendering

    Quote Originally Posted by mylogic
    Thank you so much replying to my question....

    Acutally I couldn't understand what the concept of VGFont in OpenVG is..... because I always wanted to see really 'a' or 'b' on the screen not the index..

    If so, do you have any example font paths or images..

    If you have, please let me have it from you... if not, please let me know How I can use Windows Font such as True Type Font..

    I read the specifiction of TTF, then I knew it also consisted of several paths. So, please let me see real character on my screen.
    You can simply extract font outlines (and kerning information) using the Freetype library, then you can convert them into OpenVG commands and data.
    I've written my TTF -> OpenVG 1.1 converter in a couple of hours, it's very easy (the dark side of the job is done by the Freetype library).

    For bitmap fonts you can use a root VGImage and upload a font "texture" like http://www.fontriver.com/i/maps/gothic_ ... ta_map.png
    Then you can create child images from your root image, in order to "extract" each font character.

    Happy coding
    AmanithVG Lead Programmer

  7. #7
    Junior Member
    Join Date
    Feb 2009
    Posts
    6

    Re: About Text rendering

    Now I got the concept!;;

    But, can you give me the very simple code to convert FreeType to OpenVG 1.1 path using FreeType Library.?~~

    Please... I tried to figure out the problem.. But it is difficult to me~

  8. #8
    Senior Member
    Join Date
    Feb 2006
    Posts
    115

    Re: About Text rendering

    Try font2openvg.cpp from the old hybrid site.

    http://web.archive.org/web/200708081951 ... vg.cpp.txt

    Code :
    /*
    * Copyright (c) 2006, Hybrid Graphics, Ltd.
    * All rights reserved.
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions are met:
    *
    *     * Redistributions of source code must retain the above copyright
    *       notice, this list of conditions and the following disclaimer.
    *     * Redistributions in binary form must reproduce the above copyright
    *       notice, this list of conditions and the following disclaimer in the
    *       documentation and/or other materials provided with the distribution.
    *     * The name of Hybrid Graphics may not be used to endorse or promote products
    *       derived from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY HYBRID GRAPHICS ``AS IS'' AND ANY
    * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    * DISCLAIMED. IN NO EVENT SHALL HYBRID GRAPHICS BE LIABLE FOR ANY
    * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */
     
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <float.h>
     
    #include "ft2build.h"
    #include FT_FREETYPE_H
    #include FT_OUTLINE_H
     
    #define OUTPUT_INTS
     
    class Vector2
    {
    public:
    	Vector2()						{}
    	Vector2(float px, float py)		{ x = px; y = py; }
     
    	float		x;
    	float		y;
    };
     
    Vector2	operator+(const Vector2& a, const Vector2& b)	{ return Vector2(a.x+b.x, a.y+b.y); }
    Vector2	operator*(const Vector2& a, float b)	{ return Vector2(a.x*b, a.y*b); }
     
    float convFTFixed( const FT_Pos &x )
    {
    	return (float)x / 4096.0f;
    }
     
    Vector2 convFTVector( const FT_Vector &v )
    {
    	return Vector2(convFTFixed(v.x),convFTFixed(v.y));
    }
     
    bool isOn( char b )
    {
    	return b & 1 ? true : false;
    }
     
    int main (int argc, char * const argv[])
    {
    	FT_Library library;
    	FT_Face face;
     
    	if(argc < 4)
    	{
    		printf("usage: font2openvg input_font_file output.c prefix\n");
    		exit(-1);
    	}
     
    	if( FT_Init_FreeType( &library ) )
    	{
    		printf("couldn't initialize freetype\n");
    		exit(-1);
    	}
    	int faceIndex = 0;
    	if( FT_New_Face( library, argv[1], faceIndex, &face ) )
    	{
    		printf("couldn't load new face\n");
    		exit(-1);
    	}
     
    	FT_Set_Char_Size(
                  face,    /* handle to face object           */
                  0,       /* char_width in 1/64th of points  */
                  64*64,   /* char_height in 1/64th of points */
                  96,     /* horizontal device resolution    */
                  96 );   /* vertical device resolution      */
     
    	FILE* f = fopen(argv[2], "wt");
    	if(!f)
    	{
    		printf("couldn't open %s for writing\n", argv[2]);
    		exit(-1);
    	}
     
    	std::vector<int>		gpvecindices;
    	std::vector<int>		givecindices;
    	std::vector<int>		gpvecsizes;
    	std::vector<int>		givecsizes;
    	std::vector<Vector2>	gpvec;
    	std::vector<char>		givec;
    	std::vector<float>		gbbox;
    	std::vector<float>		advances;
     
    	unsigned int characterMap[256];
    	int glyphs = 0;
    	for(int cc=0;cc<256;cc++)
    	{
    		characterMap[cc] = 0xffffffffu;	//initially nonexistent
     
    		if( cc < 32 )
    			continue;	//discard the first 32 characters
     
    		int glyphIndex = FT_Get_Char_Index( face, cc );
     
    		if( !FT_Load_Glyph( face, glyphIndex, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING | FT_LOAD_IGNORE_TRANSFORM ) )
    		{
    			float advance = convFTFixed( face->glyph->advance.x );
    			if( cc == ' ' )
    			{	//space doesn't contain any data
    				gpvecindices.push_back( gpvec.size() );
    				givecindices.push_back( givec.size() );
     
    				gpvecsizes.push_back( 0 );
    				givecsizes.push_back( 0 );
     
    				gbbox.push_back(0);
    				gbbox.push_back(0);
    				gbbox.push_back(0);
    				gbbox.push_back(0);
     
    				advances.push_back(advance);
     
    				//write glyph index to character map
    				characterMap[cc] = glyphs++;
    				continue;
    			}
     
    			FT_Outline &outline = face->glyph->outline;
    			std::vector<Vector2>		pvec;
    			std::vector<unsigned char>	ivec;
    			float minx = 10000000.0f,miny = 100000000.0f,maxx = -10000000.0f,maxy = -10000000.0f;
    			int s = 0,e;
    			bool on;
    			Vector2 last,v,nv;
    			for(int con=0;con<outline.n_contours;++con)
    			{
    				int pnts = 1;
    				e = outline.contours[con]+1;
    				last = convFTVector(outline.points[s]);
     
    				//read the contour start point
    				ivec.push_back(2);
    				pvec.push_back(last);
     
    				int i=s+1;
    				while(i<=e)
    				{
    					int c = (i == e) ? s : i;
    					int n = (i == e-1) ? s : (i+1);
    					v = convFTVector(outline.points[c]);
    					on = isOn( outline.tags[c] );
    					if( on )
    					{	//line
    						++i;
    						ivec.push_back(4);
    						pvec.push_back(v);
    						pnts += 1;
    					}
    					else
    					{	//spline
    						if( isOn( outline.tags[n] ) )
    						{	//next on
    							nv = convFTVector( outline.points[n] );
    							i += 2;
    						}
    						else
    						{	//next off, use middle point
    							nv = (v + convFTVector( outline.points[n] )) * 0.5f;
    							++i;
    						}
    						ivec.push_back(10);
    						pvec.push_back(v);
    						pvec.push_back(nv);
    						pnts += 2;
    					}
    					last = nv;
    				}
    				ivec.push_back(0);
    				s = e;
    			}
     
    			for(int i=0;i<pvec.size();++i)
    			{
    				if( pvec[i].x < minx ) minx = pvec[i].x;
    				if( pvec[i].x > maxx ) maxx = pvec[i].x;
    				if( pvec[i].y < miny ) miny = pvec[i].y;
    				if( pvec[i].y > maxy ) maxy = pvec[i].y;
    			}
    			if(!pvec.size())
    			{
    				minx = 0.0f;
    				miny = 0.0f;
    				maxx = 0.0f;
    				maxy = 0.0f;
    			}
     
    			gpvecindices.push_back( gpvec.size() );
    			givecindices.push_back( givec.size() );
     
    			gpvecsizes.push_back( pvec.size() );
    			givecsizes.push_back( ivec.size() );
     
    			gbbox.push_back( minx );
    			gbbox.push_back( miny );
    			gbbox.push_back( maxx );
    			gbbox.push_back( maxy );
    			advances.push_back(advance);
     
    			int size;
    			size = gpvec.size();
    			gpvec.resize( size + pvec.size() );
    			memcpy( &(gpvec[size]), &(pvec[0]), pvec.size() * sizeof(Vector2) );
     
    			size = givec.size();
    			givec.resize( size + ivec.size() );
    			memcpy( &(givec[size]), &(ivec[0]), ivec.size() * sizeof(char) );
     
    			//write glyph index to character map
    			characterMap[cc] = glyphs++;
    		}
    	}
    	if(!glyphs)
    		printf("warning: no glyphs found\n");
     
    	static const char* legalese = {"/* Generated by font2openvg. See [url]http://developer.hybrid.fi[/url] for more information. */\n\n"};
     
    	//print legalese
    	fprintf(f,"%s", legalese);
     
     
    	//print the name of the font file
    	fprintf (f,"/* converted from font file %s */\n", argv[1]);
    	fprintf (f,"/* font family name: %s */\n", face->family_name);
    	fprintf (f,"/* font style name: %s */\n\n", face->style_name);
     
    	//print instructions
    	fprintf (f,"static const unsigned char %s_glyphInstructions[%d] = {", argv[3],givec.size());
    	for(int i=0;i<givec.size();i++)
    	{
    		if ((i % 20)==0)
    			fprintf (f,"\n    ");
    		fprintf (f,"%d%c",givec[i],(i==(givec.size()-1))?' ':',');
    	}
    	fprintf (f,"};\n");
     
    	fprintf (f,"static const int %s_glyphInstructionIndices[%d] = {", argv[3],givecindices.size());
    	for(int i=0;i<givecindices.size();i++)
    	{
    		if ((i % 20)==0)
    			fprintf (f,"\n    ");
    		fprintf (f,"%d%c",givecindices[i],(i==(givecindices.size()-1))?' ':',');
    	}
    	fprintf (f,"};\n");
     
    	fprintf (f,"static const int %s_glyphInstructionCounts[%d] = {", argv[3],givecsizes.size());
    	for(int i=0;i<givecsizes.size();i++)
    	{
    		if ((i % 20)==0)
    			fprintf (f,"\n    ");
    		fprintf (f,"%d%c",givecsizes[i],(i==(givecsizes.size()-1))?' ':',');
    	}
    	fprintf (f,"};\n\n");
     
    	fprintf (f,"static const int %s_glyphPointIndices[%d] = {", argv[3],gpvecindices.size());
    	for(int i=0;i<gpvecindices.size();i++)
    	{
    		if ((i % 20)==0)
    			fprintf (f,"\n    ");
    		fprintf (f,"%d%c",gpvecindices[i],(i==(gpvecindices.size()-1))?' ':',');
    	}
    	fprintf (f,"};\n");
     
    #ifdef OUTPUT_INTS
    	//print points
    	fprintf (f,"static const int %s_glyphPoints[%d*2] = {", argv[3],gpvec.size());
    	for(int i=0;i<gpvec.size();i++)
    	{
    		if ((i % 10)==0)
    			fprintf (f,"\n    ");
    		fprintf (f,"%d,%d%c",(int)(65536.0f*gpvec[i].x),(int)(65536.0f*gpvec[i].y),(i==(gpvec.size()-1))?' ':',');
    	}
    	fprintf (f,"};\n");
     
    	//print the advances
    	fprintf (f,"static const int %s_glyphAdvances[%d] = {", argv[3],advances.size());
    	for(int i=0;i<advances.size();i++)
    	{
    		if ((i % 20)==0)
    			fprintf (f,"\n    ");
    		fprintf (f,"%d%c",(int)(65536.0f*advances[i]),(i==(advances.size()-1))?' ':',');
    	}
    	fprintf (f,"};\n\n");
     
    	//print the bounding boxes
    	fprintf (f,"static const int %s_glyphBBoxes[%d] = {", argv[3],gbbox.size());
    	for(int i=0;i<gbbox.size();i++)
    	{
    		if ((i % 20)==0)
    			fprintf (f,"\n    ");
    		fprintf (f,"%d%c",(int)(65536.0f*gbbox[i]),(i==(gbbox.size()-1))?' ':',');
    	}
    	fprintf (f,"};\n\n");
    #else
    	//print points
    	fprintf (f,"static const float %s_glyphPoints[%d*2] = {", argv[3],gpvec.size());
    	for(int i=0;i<gpvec.size();i++)
    	{
    		if ((i % 10)==0)
    			fprintf (f,"\n    ");
    		fprintf (f,"%f,%f%c",gpvec[i].x,gpvec[i].y,(i==(gpvec.size()-1))?' ':',');
    	}
    	fprintf (f,"};\n");
     
    	//print the advances
    	fprintf (f,"static const float %s_glyphAdvances[%d] = {", argv[3],advances.size());
    	for(int i=0;i<advances.size();i++)
    	{
    		if ((i % 20)==0)
    			fprintf (f,"\n    ");
    		fprintf (f,"%f%c",advances[i],(i==(advances.size()-1))?' ':',');
    	}
    	fprintf (f,"};\n\n");
     
    	//print the bounding boxes
    	fprintf (f,"static const float %s_glyphBBoxes[%d] = {", argv[3],gbbox.size());
    	for(int i=0;i<gbbox.size();i++)
    	{
    		if ((i % 20)==0)
    			fprintf (f,"\n    ");
    		fprintf (f,"%f%c",gbbox[i],(i==(gbbox.size()-1))?' ':',');
    	}
    	fprintf (f,"};\n\n");
    #endif
     
     
    	//print the number of glyphs and the character map
    	fprintf (f,"static const int %s_glyphCount = %d;\n",argv[3],glyphs);
    	fprintf (f,"static const short %s_characterMap[256] = {", argv[3]);
    	for(int i=0;i<256;i++)
    	{
    		if ((i % 20)==0)
    			fprintf (f,"\n    ");
    		fprintf (f,"%d%c",characterMap[i],(i==(256-1))?' ':',');
    	}
    	fprintf (f,"};\n\n");
    	fclose(f);
     
    	if(glyphs)
    		printf("%d glyphs written\n", glyphs);
     
    	FT_Done_Face( face );
    	FT_Done_FreeType( library );
        return 0;
    }

  9. #9

    Re: About Text rendering

    Hi,
    thank you, exactly what I'm looking for!

  10. #10
    Junior Member
    Join Date
    Feb 2012
    Posts
    3

    Re: About Text rendering

    Hi all, sorry but i have some trouble to build the free type library on ubuntu 10.04 and using eclipse to link can any help the macro header are alwayse get the repeat error
    Thanks

Similar Threads

  1. OpenGL text rendering
    By sdivya in forum OpenGL ES general technical discussions
    Replies: 1
    Last Post: 06-17-2012, 10:37 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •