示例#1
0
int main(int, char* argv[])
      {
      FT_Library library;

      if (FT_Init_FreeType(&library)) {
            qDebug("init free type library failed");
            exit(-1);
            }
      FT_Face face;
      int error = FT_New_Face(library, argv[1], 0, &face);
      if (error) {
            qDebug("open font failed <%s>", argv[1]);
            exit(-2);
            }

      FT_Select_Charmap(face, FT_ENCODING_UNICODE);

      FT_ULong charcode;
      FT_UInt gindex;

      for (charcode = FT_Get_First_Char(face, &gindex); gindex;
         charcode = FT_Get_Next_Char(face, charcode, &gindex)) {
            char name[256];
            FT_Get_Glyph_Name(face, gindex, name, 256);
            codemap[gindex] = charcode;
            namemap[name] = gindex;
            }
//      char* p = getTable((char*)"LILC", face);
//      parseLILC(p);
      // p = getTable("LILY", face);      // global values, not used
      // p = getTable("LILF", face);      // subfont table, not used
      genJson();
      return 0;
      }
示例#2
0
std::vector<int> Glyphs::Codepoints(std::string fontstack)
{
    std::vector<int> points;
    mapnik_fontnik::freetype_engine font_engine_;
    mapnik_fontnik::face_manager_freetype font_manager(font_engine_);

    mapnik_fontnik::font_set font_set(fontstack);
    std::stringstream stream(fontstack);
    std::string face_name;

    while (std::getline(stream, face_name, ',')) {
        font_set.add_face_name(Trim(face_name, " \t"));
    }

    mapnik_fontnik::face_set_ptr face_set;

    // This may throw.
    face_set = font_manager.get_face_set(font_set);
    for (auto const& face : *face_set) {
        FT_Face ft_face = face->get_face();
        FT_ULong  charcode;
        FT_UInt   gindex;
        charcode = FT_Get_First_Char(ft_face, &gindex);
        while (gindex != 0) {
            charcode = FT_Get_Next_Char(ft_face, charcode, &gindex);
            if (charcode != 0) points.push_back(charcode);
        }
        break;
    }

    return points;
}
示例#3
0
bool ScFace_ttf::glyphNames(ScFace::FaceEncoding& GList) const
{
	FT_ULong  charcode;
	FT_UInt gindex = 0;

	FT_Face face = ftFace();
	if (!face)
		return false;
	
	// The glyph name table embedded in Truetype fonts is not reliable.
	// For those fonts we consequently use Adobe Glyph names whenever possible.
	const bool avoidFntNames = (formatCode != ScFace::TYPE42 && typeCode == ScFace::TTF) && hasMicrosoftUnicodeCmap(face);
	if (!avoidFntNames)
		return FtFace::glyphNames(GList);
	
//	qDebug() << "reading metrics for" << face->family_name << face->style_name;
	charcode = FT_Get_First_Char(face, &gindex);
	while (gindex != 0)
	{
		GList.insert(gindex, std::make_pair(static_cast<ScFace::ucs4_type>(charcode), adobeGlyphName(charcode)));
		charcode = FT_Get_Next_Char(face, charcode, &gindex );
	}

	return true;
}
// load and store charsmaps
static void LoadCharsMaps(GFont2D& Font, const FT_Face Face) {

	GUInt32 i, numMaps;
	FT_ULong charCode;
	FT_UInt glyphIndex;
	FT_Error err;
	FT_CharMap *maps;
	FT_CharMap map;
	GEncodedChar encodedChar;
	GCharMap tmpMap;
	
	numMaps = Face->num_charmaps;
	maps = Face->charmaps;

	for (i = 0; i < numMaps; i++) {
		map = maps[i];
		err = FT_Set_Charmap(Face, map);
		if (err == 0) {
			// get first (valid) char code
			charCode = FT_Get_First_Char(Face, &glyphIndex);
			// if glyphIndex is 0, it means that charmap is empty
			if (glyphIndex != 0) {
				tmpMap.CharMap.clear();
				// store encoding informations
				tmpMap.PlatformID = map->platform_id;
				tmpMap.EncodingID = map->encoding_id;
				switch (map->encoding) {
					case FT_ENCODING_MS_SYMBOL: tmpMap.Encoding = G_ENCODING_MS_SYMBOL;
					case FT_ENCODING_UNICODE: tmpMap.Encoding = G_ENCODING_UNICODE;
					case FT_ENCODING_SJIS: tmpMap.Encoding = G_ENCODING_SJIS;
					case FT_ENCODING_GB2312: tmpMap.Encoding = G_ENCODING_GB2312;
					case FT_ENCODING_BIG5: tmpMap.Encoding = G_ENCODING_BIG5;
					case FT_ENCODING_WANSUNG: tmpMap.Encoding = G_ENCODING_WANSUNG;
					case FT_ENCODING_JOHAB: tmpMap.Encoding = G_ENCODING_JOHAB;
					case FT_ENCODING_ADOBE_STANDARD: tmpMap.Encoding = G_ENCODING_ADOBE_STANDARD;
					case FT_ENCODING_ADOBE_EXPERT: tmpMap.Encoding = G_ENCODING_ADOBE_EXPERT;
					case FT_ENCODING_ADOBE_CUSTOM: tmpMap.Encoding = G_ENCODING_ADOBE_CUSTOM;
					case FT_ENCODING_ADOBE_LATIN_1: tmpMap.Encoding = G_ENCODING_ADOBE_LATIN_1;
					case FT_ENCODING_OLD_LATIN_2: tmpMap.Encoding = G_ENCODING_OLD_LATIN_2;
					case FT_ENCODING_APPLE_ROMAN: tmpMap.Encoding = G_ENCODING_APPLE_ROMAN;
					default:
						tmpMap.Encoding = G_ENCODING_NONE;
				}
				while (glyphIndex != 0) {

					encodedChar.CharCode = (GUInt32)charCode;
					encodedChar.GlyphIndex = (GUInt32)(glyphIndex - 0);
					tmpMap.CharMap.push_back(encodedChar);
					charCode = FT_Get_Next_Char(Face, charCode, &glyphIndex);
				}
				// add the loaded charmap to the font
				Font.AddCharMap(tmpMap);
			}
		}
	}
}
示例#5
0
LEUnicode32
XeTeXFontInst_FT2::getFirstCharCode()
{
	if (!fFreeTypeOnly)
		return XeTeXFontInst::getFirstCharCode();
	else {
		FT_UInt  gindex;
		return FT_Get_First_Char(face, &gindex);
	}
}
示例#6
0
UChar32
XeTeXFontInst::getLastCharCode()
{
    FT_UInt gindex;
    UChar32 ch = FT_Get_First_Char(m_ftFace, &gindex);
    UChar32 prev = ch;
    while (gindex != 0) {
        prev = ch;
        ch = FT_Get_Next_Char(m_ftFace, ch, &gindex);
    }
    return prev;
}
示例#7
0
value ftIterateKerningPairs( value font, value callback ) {
    if( !val_is_object(font) ) {
        ft_failure_v("not a freetype font face: ", font );
    }
    value __f = val_field( font, val_id("__f") );
    if( __f == NULL || !val_is_abstract( __f ) || !val_is_kind( __f, k_ft_face ) ) {
        ft_failure_v("not a freetype font face: ", font );
    }
    FT_Face *face = val_data( __f );

	if( !FT_HAS_KERNING((*face)) ) {
		return val_null;
	}
	

	FT_UInt left_index, right_index;
	FT_ULong left, right;
	FT_Vector vec;

    left = FT_Get_First_Char( *face, &left_index );
    while( left != 0 ) {

		right = FT_Get_First_Char( *face, &right_index );
		while( right != 0 ) {

			if( !FT_Get_Kerning( *face, left_index, right_index, FT_KERNING_UNFITTED, &vec ) && vec.x ) {
//				printf("KERNING %c_%c: %f\n", left, right, vec.x );
		        val_call3( callback, alloc_int( (int)left ), alloc_int( (int)right ), alloc_float( vec.x ) );
		    }
	        
	        right = FT_Get_Next_Char( *face, right, &right_index );
	    }
            
        left = FT_Get_Next_Char( *face, left, &left_index );
    }
		
    return val_true;
}
示例#8
0
//
// _getUnicodeValues() covered in this font
//
unsigned int FontFace::_getUnicodeValues(void){
	
	FT_ULong  characterCode;                                              
	FT_UInt   glyphIndex;
	                                                
	characterCode = FT_Get_First_Char(_face, &glyphIndex);
	while(glyphIndex !=0 ){
		
		characterCode = FT_Get_Next_Char(_face,characterCode,&glyphIndex);
		_unicodeValues.insert(characterCode);
	}
	
	return _unicodeValues.size();
	
}
示例#9
0
LEUnicode32
XeTeXFontInst_FT2::getLastCharCode()
{
	if (!fFreeTypeOnly)
		return XeTeXFontInst::getLastCharCode();
	else {
		FT_UInt  gindex;
		LEUnicode32	ch = FT_Get_First_Char(face, &gindex);
		LEUnicode32	prev = ch;
		while (gindex != 0) {
			prev = ch;
			ch = FT_Get_Next_Char(face, ch, &gindex);
		}
		return prev;
	}
}
示例#10
0
Py::Object
FT2Font::get_charmap(const Py::Tuple & args) {
  _VERBOSE("FT2Font::get_charmap");
  args.verify_length(0);
  
  FT_UInt index;
  Py::Dict charmap;
  
  FT_ULong code = FT_Get_First_Char(face, &index);
  while (code != 0) {
    //charmap[Py::Long((long) code)] = Py::Int((int) index);
    charmap[Py::Int((int) index)] = Py::Long((long) code);
    code = FT_Get_Next_Char(face, code, &index);
  }
  return charmap;
}
示例#11
0
VCOS_STATUS_T vgft_font_convert_glyphs(VGFT_FONT_T *font, unsigned int char_height, unsigned int dpi_x, unsigned int dpi_y)
{
   FT_UInt glyph_index;
   FT_ULong ch;

   if (FT_Set_Char_Size(font->ft_face, 0, char_height, dpi_x, dpi_y))
   {
      FT_Done_Face(font->ft_face);
      vgDestroyFont(font->vg_font);
      return VCOS_EINVAL;
   }

   ch = FT_Get_First_Char(font->ft_face, &glyph_index);

   while (ch != 0)
   {
      if (FT_Load_Glyph(font->ft_face, glyph_index, FT_LOAD_DEFAULT)) {
         FT_Done_Face(font->ft_face);
         vgDestroyFont(font->vg_font);
         return VCOS_ENOMEM;
      }

      VGPath vg_path;
      FT_Outline *outline = &font->ft_face->glyph->outline;
      if (outline->n_contours != 0) {
         vg_path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
         assert(vg_path != VG_INVALID_HANDLE);

         convert_outline(outline->points, outline->tags, outline->contours, outline->n_contours, outline->n_points);
         vgAppendPathData(vg_path, segments_count, segments, coords);
      } else {
         vg_path = VG_INVALID_HANDLE;
      }

      VGfloat origin[] = { 0.0f, 0.0f };
      VGfloat escapement[] = { float_from_26_6(font->ft_face->glyph->advance.x), float_from_26_6(font->ft_face->glyph->advance.y) };
      vgSetGlyphToPath(font->vg_font, glyph_index, vg_path, VG_FALSE, origin, escapement);

      if (vg_path != VG_INVALID_HANDLE) {
         vgDestroyPath(vg_path);
      }
      ch = FT_Get_Next_Char(font->ft_face, ch, &glyph_index);
   }

   return VCOS_SUCCESS;
}
示例#12
0
SkUnichar SkScalerContext_CairoFT::generateGlyphToChar(uint16_t glyph)
{
    SkASSERT(fScaledFont != NULL);
    CairoLockedFTFace faceLock(fScaledFont);
    FT_Face face = faceLock.getFace();

    FT_UInt glyphIndex;
    SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex);
    while (glyphIndex != 0) {
        if (glyphIndex == glyph) {
            return charCode;
        }
        charCode = FT_Get_Next_Char(face, charCode, &glyphIndex);
    }

    return 0;
}
示例#13
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    cairo_font_options_t *font_options;
    cairo_scaled_font_t *scaled_font;
    FT_Face face;
    FT_ULong charcode;
    FT_UInt idx;
    int i = 0;
    cairo_glyph_t glyphs[NUM_GLYPHS];

    /* paint white so we don't need separate ref images for
     * RGB24 and ARGB32 */
    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
    cairo_paint (cr);

    cairo_select_font_face (cr, "Bitstream Vera Sans",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr, TEXT_SIZE);

    font_options = cairo_font_options_create ();
    cairo_get_font_options (cr, font_options);
    cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
    cairo_set_font_options (cr, font_options);
    cairo_font_options_destroy (font_options);

    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);

    scaled_font = cairo_get_scaled_font (cr);
    face = cairo_ft_scaled_font_lock_face (scaled_font);
    {
	charcode = FT_Get_First_Char(face, &idx);
	while (idx && (i < NUM_GLYPHS)) {
	    glyphs[i] = (cairo_glyph_t) {idx, PAD + GRID_SIZE * (i/GRID_ROWS), PAD + TEXT_SIZE + GRID_SIZE * (i%GRID_ROWS)};
	    i++;
	    charcode = FT_Get_Next_Char(face, charcode, &idx);
	}
    }
    cairo_ft_scaled_font_unlock_face (scaled_font);

    cairo_show_glyphs(cr, glyphs, i);

    return CAIRO_TEST_SUCCESS;
}
示例#14
0
CAMLprim value Wrapper_FT_Get_First_Char(value face)
{
  CAMLparam1(face);
  CAMLlocal1(block);
  FT_Face f;
  FT_ULong char_code;
  FT_UInt  glyph;

  f = *(FT_Face *)Data_custom_val(face);

  char_code = FT_Get_First_Char (f, &glyph);

  block = alloc_tuple(2);

  Store_field(block, 0, Val_int(char_code));
  Store_field(block, 1, Val_int(glyph));

  CAMLreturn(block);
};
示例#15
0
static PyObject *
Py_CharIter_next(Py_CharIter *self)
{
    Py_Face *face = (Py_Face *)self->base.owner;

    if (self->started) {
        self->charcode = FT_Get_Next_Char(
            face->x, self->charcode, &self->glyph_index);
    } else {
        self->charcode = FT_Get_First_Char(
            face->x, &self->glyph_index);
        self->started = 1;
    }

    if (self->glyph_index) {
        return Py_BuildValue("kI", self->charcode, self->glyph_index);
    }

    return NULL;
}
示例#16
0
int
test_cmap_iter( btimer_t*  timer,
                FT_Face    face,
                void*      user_data )
{
  FT_UInt   idx;
  FT_ULong  charcode;


  FT_UNUSED( user_data );

  TIMER_START( timer );

  charcode = FT_Get_First_Char( face, &idx );
  while ( idx != 0 )
    charcode = FT_Get_Next_Char( face, charcode, &idx );

  TIMER_STOP( timer );

  return 1;
}
示例#17
0
文件: ftdump.c 项目: xahgo/tama
  void
  Print_Charmaps( FT_Face  face )
  {
    int  i, active = -1;


    if ( face->charmap )
      active = FT_Get_Charmap_Index( face->charmap );

    /* CharMaps */
    printf( "charmaps\n" );

    for( i = 0; i < face->num_charmaps; i++ )
    {
      printf( "   %d: platform %d, encoding %d",
              i,
              face->charmaps[i]->platform_id,
              face->charmaps[i]->encoding_id );
      if ( i == active )
        printf( " (active)" );
      printf ( "\n" );

      if ( verbose )
      {
        FT_ULong  charcode;
        FT_UInt   gindex;


        FT_Set_Charmap( face, face->charmaps[i] );

        charcode = FT_Get_First_Char( face, &gindex );
        while ( gindex )
        {
          printf( "      0x%04lx => %d\n", charcode, gindex );
          charcode = FT_Get_Next_Char( face, charcode, &gindex );
        }
        printf( "\n" );
      }
    }
  }
示例#18
0
void
get_charset( FT_Face      face,
             bcharset_t*  charset )
{
  FT_ULong  charcode;
  FT_UInt   gindex;
  int i;


  charset->code = (FT_ULong*)calloc( face->num_glyphs, sizeof( FT_ULong ) );
  if ( !charset->code )
    return;

  if ( face->charmap )
  {
    i = 0;
    charcode = FT_Get_First_Char(face, &gindex);

    /* certain fonts contain a broken charmap that will map character codes */
    /* to out-of-bounds glyph indices. Take care of that here !!            */
    /*                                                                      */
    while ( gindex && i < face->num_glyphs )
    {
      charset->code[i++] = charcode;
      charcode = FT_Get_Next_Char(face, charcode, &gindex);
    }

  }
  else
  {
    /* no charmap, do an identity mapping */
    for ( i = 0; i < face->num_glyphs; i++ )
      charset->code[i] = i;
  }

  charset->size = i;
}
示例#19
0
static gchar *
check_for_ascii_glyph_numbers (FT_Face face,
                               gboolean *found_ascii)
{
    GString *ascii_string, *string;
    gulong c;
    guint glyph, found = 0;

    string = g_string_new (NULL);
    ascii_string = g_string_new (NULL);
    *found_ascii = FALSE;

    c = FT_Get_First_Char (face, &glyph);

    do {
        if (glyph == 65 || glyph == 97) {
            g_string_append_unichar (ascii_string, (gunichar) c);
            found++;
        }

        if (found == 2)
            break;

        g_string_append_unichar (string, (gunichar) c);
        c = FT_Get_Next_Char (face, c, &glyph);
    } while (glyph != 0);

    if (found == 2) {
        *found_ascii = TRUE;
        g_string_free (string, TRUE);
        return g_string_free (ascii_string, FALSE);
    } else {
        g_string_free (ascii_string, TRUE);
        return g_string_free (string, FALSE);
    }
}
示例#20
0
static gchar *
build_charlist_for_face (FT_Face face,
                         gint *length)
{
  GString *string;
  gulong c;
  guint glyph;
  gint total_chars = 0;

  string = g_string_new (NULL);

  c = FT_Get_First_Char (face, &glyph);

  while (glyph != 0) {
    g_string_append_unichar (string, (gunichar) c);
    c = FT_Get_Next_Char (face, c, &glyph);
    total_chars++;
  }

  if (length)
    *length = total_chars;

  return g_string_free (string, FALSE);
}
示例#21
0
PVOID
APIENTRY
FtfdQueryFontTree(
    DHPDEV dhpdev,
    ULONG_PTR iFile,
    ULONG iFace,
    ULONG iMode,
    ULONG_PTR *pid)
{
    PFTFD_FILE pfile = (PFTFD_FILE)iFile;
    FT_Face ftface;
    FT_Error fterror;
    FTFD_CHARPAIR *pcp;
    FD_GLYPHSET *pGlyphSet;
    FT_ULong charcode;
    ULONG i, j, cGlyphs, cRuns, cjSize;
    WCRUN *pwcrun;
    HGLYPH * phglyphs;

    DbgPrint("FtfdQueryFontTree()\n");

    fterror = FT_New_Memory_Face(gftlibrary,
                                 pfile->pvView,
                                 pfile->cjView,
                                 iFace - 1,
                                 &ftface);
    if (fterror)
    {
        DbgPrint("FT_New_Memory_Face() failed.\n");
        return NULL;
    }

    /* Get initial value for cGlyphs from ftface */
    cGlyphs = ftface->num_glyphs + 1;

    /* Allocate a buffer for the char codes and glyph indexes */
    pcp = EngAllocMem(0, cGlyphs * sizeof(FTFD_CHARPAIR), 'pcp ');
    if (!pcp)
    {
        DbgPrint("EngAllocMem() failed.\n");
        return NULL;
    }

    /* Gather char codes and indexes and count WCRUNs */
    pcp[0].code = FT_Get_First_Char(ftface, &pcp[0].index);
    charcode = pcp[0].code;
    for (i = 1, cRuns = 1; charcode && i < cGlyphs; i++)
    {
        charcode = FT_Get_Next_Char(ftface, charcode, &pcp[i].index);
        DbgPrint("charcode=0x%lx, index=0x%lx\n", charcode, pcp[i].index);
        pcp[i].code = charcode;
        if (charcode != pcp[i - 1].code + 1)
        {
            cRuns++;
        }
    }

    /* Update cGlyphs to real value */
    cGlyphs = i - 1;

    /* Calculate FD_GLYPHSET size */
    cjSize = sizeof(FD_GLYPHSET)
             + (cRuns - 1) * sizeof(WCRUN)
             + cGlyphs * sizeof(HGLYPH);

    /* Allocate the FD_GLYPHSET structure */
    pGlyphSet = EngAllocMem(0, cjSize, TAG_GLYPHSET);
    if (!pGlyphSet)
    {
        DbgPrint("EngAllocMem() failed.\n");
        return NULL;
    }

    /* Initialize FD_GLYPHSET */
    pGlyphSet->cjThis = cjSize;
    pGlyphSet->flAccel = 0;
    pGlyphSet->cGlyphsSupported = cGlyphs;
    pGlyphSet->cRuns = cRuns;

    /* Initialize 1st WCRUN */
    pwcrun = pGlyphSet->awcrun;
    phglyphs = (PHGLYPH)&pGlyphSet->awcrun[cRuns];
    pwcrun[0].wcLow = pcp[0].code;
    pwcrun[0].cGlyphs = 1;
    pwcrun[0].phg = &phglyphs[0];
    phglyphs[0] = pcp[0].index;

DbgPrint("pcp[0].index = 0x%lx\n", pcp[0].index);

    /* Walk through all supported chars */
    for (i = 1, j = 0; i < cGlyphs; i++)
    {
        /* Use glyph index as HGLYPH */
        phglyphs[i] = pcp[i].index;

        /* Check whether we can append the wchar to a run */
        if (pcp[i].code == pcp[i - 1].code + 1)
        {
            /* Append to current WCRUN */
            pwcrun[j].cGlyphs++;
        }
        else
        {
            /* Add a new WCRUN */
            DbgPrint("adding new run\n");
            j++;
            pwcrun[j].wcLow = pcp[i].code;
            pwcrun[j].cGlyphs = 1;
            pwcrun[j].phg = &phglyphs[i];
        }
    }

    /* Free the temporary buffer */
    EngFreeMem(pcp);

    /* Set *pid to the allocated structure for use in FtfdFree */
    *pid = (ULONG_PTR)pGlyphSet;

DbgPrint("pGlyphSet=%p\n", pGlyphSet);
__debugbreak();

    return pGlyphSet;
}
示例#22
0
void freeTypeFont_t :: dump() const
{
   debugPrint( "num_faces   %ld\n", face_->num_faces );
   debugPrint( "face_index    %ld\n", face_->face_index );

   debugPrint( "face_flags  %ld:\n", face_->face_flags );
   for( int mask = 1, idx = 0 ; mask <= FT_FACE_FLAG_GLYPH_NAMES ; mask <<= 1, idx++ )
   {
      if( (unsigned)idx < numFaceFlags_ )
      {
         if( 0 != ( face_->face_flags & mask ) )
            debugPrint( "   " );
         else
            debugPrint( "   !" );
         debugPrint( "%s\n", faceFlagNames_[idx] );
      }
      else
         fprintf( stderr, "How did we get here!\n" );
   } 

   debugPrint( "style_flags  %ld\n", face_->style_flags );

   debugPrint( "num_glyphs  %ld\n", face_->num_glyphs );

   debugPrint( "family_name %s\n", face_->family_name );
   debugPrint( "style_name  %s\n", face_->style_name );

   debugPrint( "num_fixed_sizes   %d\n", face_->num_fixed_sizes );
   for( int fs = 0 ; fs < face_->num_fixed_sizes ; fs++ )
   {
      debugPrint( "   %d/%d\n", face_->available_sizes[fs].width,
                            face_->available_sizes[fs].height );
   }

   debugPrint( "num_charmaps   %d\n", face_->num_charmaps );


   // the following are only relevant to scalable outlines
   //    FT_BBox           bbox;

   debugPrint( "bbox           %d/%d, %d/%d\n", face_->bbox.xMin, face_->bbox.xMax, face_->bbox.yMin, face_->bbox.yMax );
   debugPrint( "units_per_EM   %d\n", face_->units_per_EM );
   debugPrint( "ascender;      %d\n", face_->ascender );
   debugPrint( "descender      %d\n", face_->descender );
   debugPrint( "height         %d\n", face_->height );

   debugPrint( "max_advance_width %d\n", face_->max_advance_width );
   debugPrint( "max_advance_height %d\n", face_->max_advance_height );

   debugPrint( "underline_position   %d\n", face_->underline_position );
   debugPrint( "underline_thickness  %d\n", face_->underline_thickness );

   //    FT_GlyphSlot      glyph;
   //    FT_Size           size;
   //    FT_CharMap        charmap;

   for( int cm = 0; cm < face_->num_charmaps; cm++ )
   {
      FT_CharMap charmap = face_->charmaps[cm];
      debugPrint( "charmap %d =>\n", cm );
      debugPrint( "   encoding 0x%08x\n", charmap->encoding );
      debugPrint( "   platform 0x%02x\n", charmap->platform_id );
      debugPrint( "   encodeId 0x%02x\n", charmap->encoding_id );
   
      unsigned long numCharCodes = 0 ;

#define BADCHARCODE 0xFFFFaaaa
      
      FT_ULong  startCharCode = BADCHARCODE ;
      FT_ULong  prevCharCode = BADCHARCODE ;

      FT_UInt   gindex;                                                
      FT_ULong  charcode = FT_Get_First_Char( face_, &gindex );
      while( gindex != 0 )                                            
      {                                                                
         if( charcode != prevCharCode + 1 )
         {
            if( BADCHARCODE != prevCharCode )
            {
               numCharCodes += ( prevCharCode-startCharCode ) + 1 ;
            }
            startCharCode = prevCharCode = charcode ;
         }
         else
            prevCharCode = charcode ;
         charcode = FT_Get_Next_Char( face_, charcode, &gindex );        
      }                                                                
      
      if( BADCHARCODE != prevCharCode )
         numCharCodes += ( prevCharCode-startCharCode ) + 1 ;

      debugPrint( "   -> %lu charcodes\n", numCharCodes );
   }
   
   for( int fs = 0 ; fs < face_->num_fixed_sizes ; fs++ )
   {
      FT_Bitmap_Size const *bms = face_->available_sizes + fs;
      debugPrint( "fixed bitmap size %d =>\n", fs );
      debugPrint( "   height %d\n", bms->height );
      debugPrint( "   width  %d\n", bms->width );
   }
}
示例#23
0
static VFontData *objfnt_to_ftvfontdata(PackedFile *pf)
{
	/* Variables */
	FT_Face face;
	const FT_ULong charcode_reserve = 256;
	FT_ULong charcode = 0, lcode;
	FT_UInt glyph_index;
	const char *fontname;
	VFontData *vfd;

#if 0
	FT_CharMap found = 0;
	FT_CharMap charmap;
	FT_UShort my_platform_id = TT_PLATFORM_MICROSOFT;
	FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS;
	int n;
#endif

	/* load the freetype font */
	err = FT_New_Memory_Face(library,
	                         pf->data,
	                         pf->size,
	                         0,
	                         &face);

	if (err) return NULL;

#if 0
	for (n = 0; n < face->num_charmaps; n++)
	{
		charmap = face->charmaps[n];
		if (charmap->platform_id == my_platform_id &&
		    charmap->encoding_id == my_encoding_id)
		{
			found = charmap;
			break;
		}
	}

	if (!found) { return NULL; }

	/* now, select the charmap for the face object */
	err = FT_Set_Charmap(face, found);
	if (err) { return NULL; }
#endif

	/* allocate blender font */
	vfd = MEM_callocN(sizeof(*vfd), "FTVFontData");

	/* get the name */
	fontname = FT_Get_Postscript_Name(face);
	BLI_strncpy(vfd->name, (fontname == NULL) ? "" : fontname, sizeof(vfd->name));

	/* Extract the first 256 character from TTF */
	lcode = charcode = FT_Get_First_Char(face, &glyph_index);

	/* No charmap found from the ttf so we need to figure it out */
	if (glyph_index == 0) {
		FT_CharMap found = NULL;
		FT_CharMap charmap;
		int n;

		for (n = 0; n < face->num_charmaps; n++) {
			charmap = face->charmaps[n];
			if (charmap->encoding == FT_ENCODING_APPLE_ROMAN) {
				found = charmap;
				break;
			}
		}

		err = FT_Set_Charmap(face, found);

		if (err)
			return NULL;

		lcode = charcode = FT_Get_First_Char(face, &glyph_index);
	}


	/* Adjust font size */
	if (face->bbox.yMax != face->bbox.yMin) {
		vfd->scale = (float)(1.0 / (double)(face->bbox.yMax - face->bbox.yMin));
	}
	else {
		vfd->scale = 1.0f / 1000.0f;
	}

	/* Load characters */
	vfd->characters = BLI_ghash_int_new_ex(__func__, charcode_reserve);

	while (charcode < charcode_reserve) {
		/* Generate the font data */
		freetypechar_to_vchar(face, charcode, vfd);

		/* Next glyph */
		charcode = FT_Get_Next_Char(face, charcode, &glyph_index);

		/* Check that we won't start infinite loop */
		if (charcode <= lcode)
			break;
		lcode = charcode;
	}

	return vfd;
}
示例#24
0
文件: face.hpp 项目: nythil/kgascii
 boost::optional<unsigned> getFirstChar()
 {
     unsigned agindex = 0;
     unsigned charcode = FT_Get_First_Char(handle_, &agindex);
     return boost::make_optional(agindex != 0, charcode);
 }
示例#25
0
/**
 * Main.
 */
int main(int argc, char* argv[]) {
    FT_Error error;
    std::string fTtf;
    std::string fCxf;

    // init:
    fpCxf = NULL;
	nodes = 4;
    name = "Unknown";
    letterSpacing = 3.0;
    wordSpacing = 6.75;
    lineSpacingFactor = 1.0;
    author = "Unknown";

    // handle arguments:
    if (argc<2) {
        std::cout << "Usage: ttf2cxf <options> <ttf file> <cxf file>\n";
        std::cout << "  ttf file: An existing True Type Font file\n";
        std::cout << "  cxf file: The CXF font file to create\n";
		std::cout << "options are:\n";
        std::cout << "  -n nodes                 Number of nodes for quadratic and cubic splines (int)\n";
        std::cout << "  -a author                Author of the font. Preferably full name and e-mail address\n";
        std::cout << "  -l letter spacing        Letter spacing (float)\n";
        std::cout << "  -w word spacing          Word spacing (float)\n";
        std::cout << "  -f line spacing factor   Default is 1.0 (float)\n";
        exit(1);
    }

	for (int i=1; i<argc; ++i) {
		if (!strcmp(argv[i], "-n")) {
			++i;
			nodes = atoi(argv[i]);
		}
		else if (!strcmp(argv[i], "-a")) {
			++i;
			author = argv[i];
		}
		else if (!strcmp(argv[i], "-l")) {
			++i;
			letterSpacing = atof(argv[i]);
		}
		else if (!strcmp(argv[i], "-w")) {
			++i;
			wordSpacing = atof(argv[i]);
		}
		else if (!strcmp(argv[i], "-f")) {
			++i;
			lineSpacingFactor = atof(argv[i]);
		}
	}

    fTtf = argv[argc-2];
    fCxf = argv[argc-1];

    std::cout << "TTF file: " << fTtf.c_str() << "\n";
    std::cout << "CXF file: " << fCxf.c_str() << "\n";

    // init freetype
    error = FT_Init_FreeType(&library);
    if (error) {
        std::cerr << "Error: FT_Init_FreeType\n";
    }

    // load ttf font
    error = FT_New_Face(library,
                        fTtf.c_str(),
                        0,
                        &face);
    if (error==FT_Err_Unknown_File_Format) {
        std::cerr << "FT_New_Face: Unknown format\n";
    } else if (error) {
        std::cerr << "FT_New_Face: Unknown error\n";
    }

    std::cout << "family: " << face->family_name << "\n";
	name = face->family_name;
    std::cout << "height: " << face->height << "\n";
    std::cout << "ascender: " << face->ascender << "\n";
    std::cout << "descender: " << face->descender << "\n";

    // find out height by tracing 'A'
    yMax = -1000;
    convertGlyph(65);
    factor = 1.0/(1.0/9.0*yMax);

    std::cout << "factor: " << factor << "\n";

    // write font file:
    fpCxf = fopen(fCxf.c_str(), "wt");
    if (fpCxf==NULL) {
        std::cerr << "Cannot open file " << fCxf.c_str() << " for writing.\n";
        exit(2);
    }

    // write font header
    fprintf(fpCxf, "# Format:            QCad 2 Font\n");
    fprintf(fpCxf, "# Creator:           ttf2cxf\n");
    fprintf(fpCxf, "# Version:           1\n");
    fprintf(fpCxf, "# Name:              %s\n", name.c_str());
    fprintf(fpCxf, "# LetterSpacing:     %f\n", letterSpacing);
    fprintf(fpCxf, "# WordSpacing:       %f\n", wordSpacing);
    fprintf(fpCxf, "# LineSpacingFactor: %f\n", lineSpacingFactor);
    fprintf(fpCxf, "# Author:            %s\n", author.c_str());
    fprintf(fpCxf, "\n");

    uint first;
    FT_Get_First_Char(face, &first);

    FT_ULong  charcode;
    FT_UInt   gindex;

	// iterate through glyphs
    charcode = FT_Get_First_Char( face, &gindex );
    while (gindex != 0) {
        convertGlyph(charcode);
        charcode = FT_Get_Next_Char(face, charcode, &gindex);
    }

	return 0;
}
示例#26
0
void PdfFontCID::CreateCMap( PdfObject* pUnicode ) const
{
    PdfFontMetricsFreetype* pFreetype = dynamic_cast<PdfFontMetricsFreetype*>(m_pMetrics);
	if (!pFreetype) return;

    int  nFirstChar = m_pEncoding->GetFirstChar();
    int  nLastChar  = m_pEncoding->GetLastChar();

    std::ostringstream oss;

    FT_Face   face = pFreetype->GetFace();
    FT_ULong  charcode;                                              
    FT_UInt   gindex;                                                

    TBFRange curRange;
    curRange.srcCode = -1;
    std::vector<TBFRange> vecRanges;
    // Only 255 sequent characters are allowed to be in one range!
    const unsigned int MAX_CHARS_IN_RANGE = 255;

    charcode = FT_Get_First_Char( face, &gindex );                   
    while ( gindex != 0 )                                            
    {        
        if( static_cast<int>(charcode) > nLastChar )
        {
            break;
        }
        else if( static_cast<int>(charcode) >= nFirstChar )
        {
            if( curRange.vecDest.size() == 0 ) 
            {
                curRange.srcCode  = gindex;
                curRange.vecDest.push_back( charcode );
            }
            else if( (curRange.srcCode + curRange.vecDest.size() == gindex) && 
                     ((gindex - curRange.srcCode + curRange.vecDest.size()) < MAX_CHARS_IN_RANGE) )
            {
                curRange.vecDest.push_back( charcode );
            } 
            else
            {
                // Create a new bfrange
                vecRanges.push_back( curRange );
                curRange.srcCode = gindex;
                curRange.vecDest.clear();
                curRange.vecDest.push_back( charcode );
            }
        }

        charcode = FT_Get_Next_Char( face, charcode, &gindex );        
    }   

    if( curRange.vecDest.size() ) 
        vecRanges.push_back( curRange );

    // Now transform it into a string
    // Make sure each bfrange section has a maximum of 
    // 100 entries. If there are more Acrobat Reader might crash
    std::ostringstream range;
    int numberOfEntries = 0;

    std::vector<TBFRange>::const_iterator it = vecRanges.begin();

    const int BUFFER_LEN = 5;
    char buffer[BUFFER_LEN]; // buffer of the format "XXXX\0"
    
    while( it != vecRanges.end() ) 
    {
        if( numberOfEntries == 99 ) 
        {
            oss << numberOfEntries << " beginbfrange" << std::endl;
            oss << range.str();
            oss << "endbfrange" << std::endl;

            numberOfEntries = 0;
            range.str("");
        }

        pdf_long iStart = (*it).srcCode;
        pdf_long iEnd   = (*it).srcCode + (*it).vecDest.size() - 1;

        snprintf( buffer, BUFFER_LEN, "%04X", static_cast<unsigned int>(iStart) );
        range << "<" << buffer << "> <";
        snprintf( buffer, BUFFER_LEN, "%04X", static_cast<unsigned int>(iEnd) );
        range << buffer << "> [ ";

        std::vector<int>::const_iterator it2 = (*it).vecDest.begin();
        while( it2 != (*it).vecDest.end() )
        {
            snprintf( buffer, BUFFER_LEN, "%04X", *it2 );
            range << "<" << buffer << "> ";

            ++it2;
        }

        range << "]" << std::endl;
        ++it;
        ++numberOfEntries;
    }

    if( numberOfEntries > 0 ) 
    {
        oss << numberOfEntries << " beginbfrange" << std::endl;
        oss << range.str();
        oss << "endbfrange" << std::endl;
    }

    /*
    // Create the beginbfchar section
    std::ostringstream oss;
    std::ostringstream tmp;
    const int BUFFER_LEN = 14;
    char buffer[BUFFER_LEN]; // buffer of the format "<XXXX> <XXXX>\0"
    
    bool bLittle = podofo_is_little_endian();
    int  nCount  = 1;

    while( nFirstChar <= nLastChar ) 
    {
        lGlyph = m_pMetrics->GetGlyphId( nFirstChar );
        if( lGlyph && lGlyph <= 0xffff)
        {
            if( bLittle ) 
                snprintf( buffer, BUFFER_LEN, "<%04X> <%04X>", static_cast<unsigned int>(lGlyph), 
                          ((nFirstChar & 0xff00) >> 8) | ((nFirstChar & 0x00ff) << 8) );
            else
                snprintf( buffer, BUFFER_LEN, "<%04X> <%04X>", static_cast<unsigned int>(lGlyph), nFirstChar );

            tmp << buffer << std::endl;

            if( nCount % 100 == 0 )
            {
                // There can be at maximum 100 lines in a bfchar section
                oss << nCount - 1 << " beginbfchar" << std::endl << tmp.str() << "endbfchar" << std::endl;
                tmp.str(""); // clear the stream
                nCount = 0;
            }

            ++nCount;
        }
        
        ++nFirstChar;
    }

    if( nCount > 1 )
        oss << nCount - 1 << " beginbfchar" << std::endl << tmp.str() << "endbfchar" << std::endl;
    */

    // Create the CMap
    pUnicode->GetStream()->BeginAppend();
    pUnicode->GetStream()->Append("/CIDInit /ProcSet findresource begin\n");
    pUnicode->GetStream()->Append("10000 dict begin\n");
    pUnicode->GetStream()->Append("begincmap\n");
    pUnicode->GetStream()->Append("/CIDSystemInfo\n");
    pUnicode->GetStream()->Append("<< /Registry (Adobe)\n");
    pUnicode->GetStream()->Append("/Ordering (UCS)\n");
    pUnicode->GetStream()->Append("/Supplement 0\n");
    pUnicode->GetStream()->Append(">> def\n");
    pUnicode->GetStream()->Append("/CMapName /Adobe-Identity-UCS def\n");
    pUnicode->GetStream()->Append("/CMapType 2 def\n");
    pUnicode->GetStream()->Append("1 begincodespacerange\n");
    pUnicode->GetStream()->Append("<0000> <FFFF>\n");
    pUnicode->GetStream()->Append("endcodespacerange\n");
    pUnicode->GetStream()->Append( oss.str().c_str() );
    pUnicode->GetStream()->Append("endcmap\n");
    pUnicode->GetStream()->Append("CMapName currentdict /CMap defineresource pop\n");
    pUnicode->GetStream()->Append("end\n");
    pUnicode->GetStream()->Append("end\n");
    pUnicode->GetStream()->EndAppend();
}
示例#27
0
static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
{
	// Variables
	FT_Face face;
	FT_ULong charcode = 0, lcode;
	FT_UInt glyph_index;
	const char *fontname;
	VFontData *vfd;

/*
	FT_CharMap  found = 0;
	FT_CharMap  charmap;
	FT_UShort my_platform_id = TT_PLATFORM_MICROSOFT;
	FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS;
	int         n;
*/

	// load the freetype font
	err = FT_New_Memory_Face( library,
						pf->data,
						pf->size,
						0,
						&face );

	if(err) return NULL;
/*
	for ( n = 0; n < face->num_charmaps; n++ )
	{
		charmap = face->charmaps[n];
		if ( charmap->platform_id == my_platform_id &&
			charmap->encoding_id == my_encoding_id )
		{
			found = charmap;
			break;
		}
	}

	if ( !found ) { return NULL; }

	// now, select the charmap for the face object
	err = FT_Set_Charmap( face, found );
	if ( err ) { return NULL; }
*/

	// allocate blender font
	vfd= MEM_callocN(sizeof(*vfd), "FTVFontData");

	// get the name
	fontname = FT_Get_Postscript_Name(face);
	strcpy(vfd->name, (fontname == NULL) ? "" : fontname);

	// Extract the first 256 character from TTF
	lcode= charcode= FT_Get_First_Char(face, &glyph_index);

	// No charmap found from the ttf so we need to figure it out
	if(glyph_index == 0)
	{
		FT_CharMap  found = NULL;
		FT_CharMap  charmap;
		int n;

		for ( n = 0; n < face->num_charmaps; n++ )
		{
			charmap = face->charmaps[n];
			if (charmap->encoding == FT_ENCODING_APPLE_ROMAN)
			{
				found = charmap;
				break;
			}
		}

		err = FT_Set_Charmap( face, found );

		if( err ) 
			return NULL;

		lcode= charcode= FT_Get_First_Char(face, &glyph_index);
	}

	// Load characters
	while(charcode < 256)
	{
		// Generate the font data
		freetypechar_to_vchar(face, charcode, vfd);

		// Next glyph
		charcode = FT_Get_Next_Char(face, charcode, &glyph_index);

		// Check that we won't start infinite loop
		if(charcode <= lcode)
			break;
		lcode = charcode;
	}

	return vfd;	
}
示例#28
0
UChar32
XeTeXFontInst::getFirstCharCode()
{
    FT_UInt gindex;
    return FT_Get_First_Char(m_ftFace, &gindex);
}
示例#29
0
void importDefineFont2( DefineFont2 *tag, const char *filename, xmlNodePtr node ) {
	FT_Library swfft_library;
	FT_Face face;
	int error;
	FT_UInt glyph_index;
	FT_ULong character;
	FT_Outline *outline;
	xmlChar *glyphs_xml = xmlGetProp( node, (const xmlChar *)"glyphs" );
	const char *glyphs = (const char *)glyphs_xml;
	
	GlyphList *glyphList = tag->getglyphs();
	List<Short>* advance = tag->getadvance();
	List<Rectangle>* bounds = tag->getbounds();
	// NYI: kerning
	
	Shape *shape;
	int glyph_n;
	int n, ofs;
	
	if( FT_Init_FreeType( &swfft_library ) ) {
		fprintf( stderr, "WARNING: could not initialize FreeType\n" );
		goto fail;
	}
	
	error = FT_New_Face( swfft_library, filename, 0, &face );
	if( error ) {
		fprintf( stderr, "WARNING: FreeType does not like %s\n", filename );
		goto fail;
	}

	if( face->num_faces > 1 ) {
		fprintf( stderr, "WARNING: %s contains %i faces, but only the first is imported.\n", filename, face->num_faces );
	}
	
	if( face->charmap == 0 ) {
		fprintf( stderr, "WARNING: %s doesn't seem to contain a unicode charmap.\n", filename );
	}

	FT_Set_Char_Size(face, 1024<<6, 1024<<6, 75, 75);

	// we should only import @glyphs, lets do all for now.
	
	// count availably glyphs
	n = 0;
	if( (character = FT_Get_First_Char( face, &glyph_index )) != 0 ) n++;
	while( (character = FT_Get_Next_Char( face, character, &glyph_index )) != 0 ) n++;

	if( n>255 ) n=255; // FIXME
	ofs = 0;
	n-=ofs;
	
	fprintf( stderr, "importing %s: %i glyphs\n", filename, n );

	glyphList->allocate( n );
	tag->setglyphCount( n );
	tag->setname( "helvetica" ); // FIXME
	tag->sethasLayout( 1 );
	tag->setascent( face->ascender * 1024 / face->units_per_EM );
	tag->setdescent( labs(face->descender)* 1024 / face->units_per_EM );
	tag->setleading( face->height* 1024 / face->units_per_EM );
	tag->setwideGlyphOffsets( 1 );
	tag->setwideMap( 1 );
	
	character = FT_Get_First_Char( face, &glyph_index );
	for( int i=0; i<ofs; i++ ) character=FT_Get_Next_Char( face, character, &glyph_index );
	for( int glyph_n=0; character && glyph_n<n; glyph_n++ ) {
	
//		glyph_index = FT_Get_Char_Index( face, character );
		if( FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_BITMAP ) ) {
			fprintf( stderr, "WARNING: couldnt load glyph %i (%c) from %s.\n", character, character, filename );
		}

		if( face->glyph->format != FT_GLYPH_FORMAT_OUTLINE ) {
			fprintf( stderr, "WARNING: %s seems to be a bitmap font.\n", filename );
			goto fail;
		}

		outline = &face->glyph->outline;
		
//		fprintf(stderr,"importing glyph %i ('%c') of %s (advance %i, %i points)\n", character, character, filename, face->glyph->advance.x, outline->n_points );
		{
			Short *adv = new Short();
			adv->setvalue( (short)(face->glyph->advance.x * (1.0/64)) );
			advance->append(adv);
			
			Rectangle *r = new Rectangle();
/*			r->settop( -face->bbox.yMax * 1024 / face->units_per_EM );
			r->setright( face->bbox.xMax - face->bbox.xMin );
			r->setbottom( -face->bbox.yMin * 1024 / face->units_per_EM );
*/			r->setbits( SWFMaxBitsNeeded( true, 3, r->gettop(), r->getright(), r->getbottom() ) );
			bounds->append(r);
			
			glyphList->setMapN(glyph_n, character);
			shape = glyphList->getShapeN(glyph_n);
			ShapeMaker shaper( shape->getedges(), (1.0/64), -(1.0/64), 0, 0 );

			// set fillBits
			shape->setfillBits(1);
			
			int start = 0, end;
			bool control, cubic;
			int n;
			for( int contour = 0; contour < outline->n_contours; contour++ ) {
				end = outline->contours[contour];
	//			fprintf(stderr,"  contour %i: %i-%i\n", contour, start, end );
				n=0;

				for( int p = start; p<=end; p++ ) {
					control = !(outline->tags[p] & 0x01);
					cubic = outline->tags[p] & 0x02;
					
	/*				if( character == 'h' ) 
					fprintf( stderr, "   point %i: %s%s %i %i\n", p, 
						control?(cubic?"third-order ":"second-order "):"",
						control?"control":"on-curve",
						outline->points[p].x, outline->points[p].y);
	*/				
						if( p==start ) {
							shaper.setup( outline->points[p-n].x, outline->points[p-n].y, 1 );
						}
					if( !control && n > 0 ) {
						importGlyphPoints( &(outline->points[(p-n)+1]), n-1, shaper, cubic );
						n=1;
					} else {
						n++;
					}
				}
				
				if( n ) {
					// special case: repeat first point
					FT_Vector points[n+1];
					int s=(end-n)+2;
					for( int i=0; i<n-1; i++ ) {
						points[i].x = outline->points[s+i].x;
						points[i].y = outline->points[s+i].y;
					}
					points[n-1].x = outline->points[start].x;
					points[n-1].y = outline->points[start].y;
					
					importGlyphPoints( points, n-1, shaper, false );
				}
				
				shaper.close();
				
				start = end+1;
			}
				
			shaper.finish();
		}
		
		character = FT_Get_Next_Char( face, character, &glyph_index );
	}
	
	return;
		
fail:
	fprintf( stderr, "WARNING: could not import %s\n", filename );
	return;
}
示例#30
0
/**
 * Main.
 */
int main(int argc, char* argv[]) {
    FT_Error error;
    std::string fTtf;
    std::string fLff;

    // init:
    fpLff = NULL;
    nodes = 4;
    std::string name = "Unknown";
    double letterSpacing = 3.0;
    double wordSpacing = 6.75;
    double lineSpacingFactor = 1.0;
    std::string author = "Unknown";
    std::string license = "Unknown";
    precision = 6;

    // handle arguments:
    if (argc<2) {
        std::cout << "Usage: ttf2cxf <options> <ttf file> <cxf file>\n";
        std::cout << "  ttf file: An existing True Type Font file\n";
        std::cout << "  lff file: The LFF font file to create\n";
        std::cout << "options are:\n";
        std::cout << "  -n nodes                 Number of nodes for quadratic and cubic splines (int)\n";
        std::cout << "  -a author                Author of the font. Preferably full name and e-mail address\n";
        std::cout << "  -l letter spacing        Letter spacing (float)\n";
        std::cout << "  -w word spacing          Word spacing (float)\n";
        std::cout << "  -f line spacing factor   Default is 1.0 (float)\n";
        std::cout << "  -d precision             Number of decimal digits (int)\n";
        std::cout << "  -L license               license of the font.\n";
        exit(1);
    }

    for (int i=1; i<argc; ++i) {
        if (!strcmp(argv[i], "-n")) {
            ++i;
            nodes = atoi(argv[i]);
        }
        else if (!strcmp(argv[i], "-a")) {
            ++i;
            author = argv[i];
        }
        else if (!strcmp(argv[i], "-l")) {
            ++i;
            letterSpacing = atof(argv[i]);
        }
        else if (!strcmp(argv[i], "-w")) {
            ++i;
            wordSpacing = atof(argv[i]);
        }
        else if (!strcmp(argv[i], "-d")) {
            ++i;
            precision = atoi(argv[i]);
        }
        else if (!strcmp(argv[i], "-f")) {
            ++i;
            lineSpacingFactor = atof(argv[i]);
        }
        else if (!strcmp(argv[i], "-L")) {
            ++i;
            license = argv[i];
        }
    }

    fTtf = argv[argc-2];
    fLff = argv[argc-1];

    std::cout << "TTF file: " << fTtf.c_str() << "\n";
    std::cout << "LFF file: " << fLff.c_str() << "\n";

    // init freetype
    error = FT_Init_FreeType(&library);
    if (error) {
        std::cerr << "Error: FT_Init_FreeType\n";
    }

    // load ttf font
    error = FT_New_Face(library,
                        fTtf.c_str(),
                        0,
                        &face);
    if (error==FT_Err_Unknown_File_Format) {
        std::cerr << "FT_New_Face: Unknown format\n";
    } else if (error) {
        std::cerr << "FT_New_Face: Unknown error\n";
    }

    std::cout << "family: " << face->family_name << "\n";
    name = face->family_name;
    std::cout << "height: " << face->height << "\n";
    std::cout << "ascender: " << face->ascender << "\n";
    std::cout << "descender: " << face->descender << "\n";

    // find out height by tracing 'A'
    yMax = -1000;
    convertGlyph(65);
    factor = 1.0/(1.0/9.0*yMax);

    std::cout << "factor: " << factor << "\n";

    // write font file:
    fpLff = fopen(fLff.c_str(), "wt");
    if (fpLff==NULL) {
        std::cerr << "Cannot open file " << fLff.c_str() << " for writing.\n";
        exit(2);
    }

    sprintf(numFormat,"%%.%if", precision);

    // write font header
    fprintf(fpLff, "# Format:            LibreCAD Font 1\n");
    fprintf(fpLff, "# Creator:           ttf2lff\n");
    fprintf(fpLff, "# Version:           1\n");
    fprintf(fpLff, "# Name:              %s\n", name.c_str());
    fprintf(fpLff, "# LetterSpacing:     %s\n", clearZeros(letterSpacing).c_str());
    fprintf(fpLff, "# WordSpacing:       %s\n", clearZeros(wordSpacing).c_str());
    fprintf(fpLff, "# LineSpacingFactor: %s\n", clearZeros(lineSpacingFactor).c_str());

    time_t rawtime;
    struct tm * timeinfo;
    char buffer [12];
    time ( &rawtime );
    timeinfo = localtime ( &rawtime );
    strftime (buffer,80,"%Y-%m-%d",timeinfo);

    fprintf(fpLff, "# Created:           %s\n", buffer);
    fprintf(fpLff, "# Last modified:     %s\n", buffer);
    fprintf(fpLff, "# Author:            %s\n", author.c_str());
    fprintf(fpLff, "# License:           %s\n", license.c_str());
    fprintf(fpLff, "\n");

    uint first;
    FT_Get_First_Char(face, &first);

    FT_ULong  charcode;
    FT_UInt   gindex;

    // iterate through glyphs
    charcode = FT_Get_First_Char( face, &gindex );
    while (gindex != 0) {
        convertGlyph(charcode);
        charcode = FT_Get_Next_Char(face, charcode, &gindex);
    }

    return 0;
}