Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a glyph outline of a true type character on a linux system

I'm searching for a library to get the outline of a glyph in a true type font on a linux system. We are using Pango and Cairo but unfortunatly I didn't find anything. I'm looking for somethig similar to GlyphTypeface.GetGlyphOutline under .NET

Any help or hints are appreciated!

Thanks in advance

like image 880
chrmue Avatar asked Dec 22 '22 03:12

chrmue


2 Answers

The solution is to use FreeType, it offers the range of function I need:

#include <string>
#include <iostream>
#include  <freetype/ftglyph.h>
#include  <freetype/freetype.h>

//******************* check error code ********************
void Check(FT_Error ErrCode, const char* OKMsg, const char* ErrMsg)
{
  if(ErrCode != 0)
  {
std::cout << ErrMsg << ": " << ErrCode << "\n";
std::cout << "program halted\n";
exit(1);
  }
  else
    std::cout << OKMsg << "\n";
  }

//******************** get outline ************************
int GetOutLine(FT_Glyph glyph, FT_OutlineGlyph* Outg)
{
  int Err = 0;

  switch ( glyph->format )
  {
    case FT_GLYPH_FORMAT_BITMAP:
      Err = 1;
      break;

    case FT_GLYPH_FORMAT_OUTLINE:
      *Outg = (FT_OutlineGlyph)glyph;
      break;

    default:
      ;
  }
  return Err;
}

//*********** print outline  to console ***************
int PrintOutLine(FT_OutlineGlyph Outg)
{
int Err = 0;
FT_Outline* Ol = &Outg->outline;
int Start = 0;                   //start index of contour
int End = 0;                     //end index of contour
short* pContEnd = Ol->contours;  //pointer to contour end
FT_Vector* pPoint = Ol->points;  //pointer to outline point
    char* pFlag = Ol->tags;          //pointer to flag

for(int c = 0; c < Ol->n_contours; c++)
{
    std::cout << "\nContour " << c << ":\n";
    End = *pContEnd++;
    for(int p = Start; p <= End; p++)
    {
        char Ch = *pFlag++ + '0';
        std::cout << "Point " << p <<": X=" << pPoint->x << " Y="<<pPoint->y << " Flag=" << Ch << "\n";
        pPoint++;
    }
    Start = End + 1;
} 

return Err;
}

//*********** get glyph index from command line *************
 FT_UInt GetGlyphIndex(int argc, char* argv[], int Nr)
 {
if(argc > Nr)
{
  return atoi(argv[Nr]);
}
else
{
  return 36;
}
 } 

//*********** get font name from command line *************
 void GetFontName(int argc, char* argv[], int Nr, std::string& FontName)
 {
if(argc > Nr)
{
  FontName += argv[Nr]; 
}
else
{
  FontName += "FreeMono.ttf";
}
 } 

 //*********** get font size from command line *************
 int GetFontSize(int argc, char* argv[], int Nr)
 {
   short FontSize = 50 * 64;
   if(argc > Nr)
     FontSize += atoi(argv[Nr]); 
   return FontSize;
 } 

//******************** M A I N ************************
// par1: FontName, par2:Glyph-Nr, par3: FontSize as FT_F26Dot6
int main(int argc, char* argv[])
{
  FT_Face face;
  FT_Library    library;
  FT_Error error;

  error = FT_Init_FreeType( &library );
  Check(error, "", "error initializing FT lib");

  std::string FontName;
  FontName = "/usr/share/fonts/truetype/freefont/";
  GetFontName(argc, argv, 1, FontName);
  error = FT_New_Face( library, FontName.c_str(), 0, &face );   
  Check(error, "",  "error loading font");

  FT_F26Dot6 font_size = GetFontSize(argc, argv, 3);
  error = FT_Set_Char_Size( face, font_size, font_size, 72, 72 );
  Check(error, "", "error setting char size");

  FT_UInt   glyph_index = GetGlyphIndex(argc, argv, 2);
  FT_Int32  load_flags = FT_LOAD_DEFAULT;   
  error = FT_Load_Glyph( face,  glyph_index, load_flags );      
  Check(error, "", "error loading glyph");

  FT_Glyph glyph; 
  error = FT_Get_Glyph( face->glyph, &glyph );  
  Check(error, "", "error getting glyph");

  FT_OutlineGlyph Outg;
  error = GetOutLine(glyph, &Outg);
  Check(error,"", "error getting outline"); 

  std::cout << "=======================================================\n";
  std::cout << "Font: " << FontName << "\n";
  std::cout << "Glyph Index: " << glyph_index << "\n";
  std::cout << "=======================================================\n";
  error = PrintOutLine(Outg);
  Check(error,"", "error printing outline"); 

  return 0;  
}
like image 195
chrmue Avatar answered Apr 06 '23 10:04

chrmue


Cairo has this capability builtin.

cairo_glyph_path() will get the glyph outline and make it the current path, and allow you to get the current path and iterate over it.

like image 40
John D. Avatar answered Apr 06 '23 10:04

John D.