Esempio n. 1
0
void root_window_free()
{
    if (is_init)
    {
        free_font(font); // free freetype font used
    }
}
Esempio n. 2
0
NewFont *NewFont::loadFont(Common::SeekableReadStream &stream) {
	NewFontData *data = bdf_read_font(stream);
	if (!data || stream.err()) {
		free_font(data);
		return 0;
	}

	FontDesc desc;
	desc.name = data->name;
	desc.maxwidth = data->maxwidth;
	desc.height = data->height;
	desc.fbbw = data->fbbw;
	desc.fbbh = data->fbbh;
	desc.fbbx = data->fbbx;
	desc.fbby = data->fbby;
	desc.ascent = data->ascent;
	desc.firstchar = data->firstchar;
	desc.size = data->size;
	desc.bits = data->bits;
	desc.offset = data->offset;
	desc.width = data->width;
	desc.bbx = data->bbx;
	desc.defaultchar = data->defaultchar;
	desc.bits_size = data->bits_size;

	return new NewFont(desc, data);
}
Esempio n. 3
0
/* build incore structure from .bdf file*/
NewFontData* bdf_read_font(Common::SeekableReadStream &fp) {
	NewFontData* pf;
	uint32 pos = fp.pos();

	pf = (NewFontData*)calloc(1, sizeof(NewFontData));
	if (!pf)
		goto errout;

	if (!bdf_read_header(fp, pf)) {
		warning("Error reading font header");
		goto errout;
	}

	fp.seek(pos, SEEK_SET);

	if (!bdf_read_bitmaps(fp, pf)) {
		warning("Error reading font bitmaps");
		goto errout;
	}

	return pf;

 errout:
	free_font(pf);
	return NULL;
}
int load_font(char *fname, int size) {
	char *p;

	free_font();
	font = TTF_OpenFont(fname, size);

	if (!font) {
		//Try to open the in memory font
		SDL_RWops *s;
		s = SDL_RWFromMem(dejavu_sans_ttf, dejavu_sans_ttf_len);
		font = TTF_OpenFontRW(s, 0, size);
		if (font) {
			__android_log_print(ANDROID_LOG_INFO, "BroovPlayer",
					"Open font from memory successful");
		} else {
			__android_log_print(ANDROID_LOG_INFO, "BroovPlayer",
					"Open font from memory failed:%s",
					TTF_GetError());
			return 3;
		}

	}

	/* print some metrics and attributes */
	//printf("size                    : %d\n",size);
	//printf("TTF_FontHeight          : %d\n",TTF_FontHeight(font));
	//printf("TTF_FontAscent          : %d\n",TTF_FontAscent(font));
	//printf("TTF_FontDescent         : %d\n",TTF_FontDescent(font));
	//printf("TTF_FontLineSkip        : %d\n",TTF_FontLineSkip(font));
	//printf("TTF_FontFaceIsFixedWidth: %d\n",TTF_FontFaceIsFixedWidth(font));
	/* cache new glyphs */
	cache_glyphs();

	return 0;
}
Esempio n. 5
0
static duk_ret_t
js_Font_finalize(duk_context* ctx)
{
	font_t* font;

	font = duk_require_sphere_obj(ctx, 0, "Font");
	free_font(font);
	return 0;
}
Esempio n. 6
0
static duk_ret_t
js_Font_finalize(duk_context* ctx)
{
	font_t* font;

	duk_get_prop_string(ctx, 0, "\xFF" "ptr"); font = duk_get_pointer(ctx, -1); duk_pop(ctx);
	free_font(font);
	return 0;
}
Esempio n. 7
0
void load_font(char *fname, int size)
{
    char *p;

    free_font();
    font=TTF_OpenFont(fname, size);
    if(!font)
    {
        printf("TTF_OpenFont: %s\n", TTF_GetError());
        exit(3);
    }

    /* print some metrics and attributes */
    printf("size                    : %d\n",size);
    printf("TTF_FontHeight          : %d\n",TTF_FontHeight(font));
    printf("TTF_FontAscent          : %d\n",TTF_FontAscent(font));
    printf("TTF_FontDescent         : %d\n",TTF_FontDescent(font));
    printf("TTF_FontLineSkip        : %d\n",TTF_FontLineSkip(font));
    printf("TTF_FontFaceIsFixedWidth: %d\n",TTF_FontFaceIsFixedWidth(font));
    {
        char *str=TTF_FontFaceFamilyName(font);
        if(!str)
            str="(null)";
        printf("TTF_FontFaceFamilyName  : \"%s\"\n",str);
    }
    {
        char *str=TTF_FontFaceStyleName(font);
        if(!str)
            str="(null)";
        printf("TTF_FontFaceStyleName   : \"%s\"\n",str);
    }
    if(TTF_GlyphIsProvided(font,'g'))
    {
        int minx, maxx, miny, maxy, advance;
        TTF_GlyphMetrics(font,'g', &minx, &maxx, &miny, &maxy, &advance);
        printf("TTF_GlyphMetrics('g'):\n\tminx=%d\n\tmaxx=%d\n\tminy=%d\n\tmaxy=%d\n\tadvance=%d\n",
            minx, maxx, miny, maxy, advance);
    }
    else
        printf("TTF_GlyphMetrics('g'): unavailable in font!\n");

    /* set window title and icon name, using filename and stuff */
    p=strrchr(fname,'/');
    if(!p)
        p=strrchr(fname,'\\');
    if(!p)
        p=strrchr(fname,':');
    if(!p)
        p=fname;
    else
        p++;

    /* cache new glyphs */
    cache_glyphs();
}
Esempio n. 8
0
/*! load font info
 *
 *  @param[in] name
 *  @param[in] pt
 *  @param[in] render_data
 *  @param[in] render_data_size
 *  @param[in] kerning data
 *  @param[in] kerning_data_size
 *
 *  @returns font info
 */
static font_t*
load_font(const char *name,
          int        pt,
          const u8   *render_data,
          size_t     render_data_size,
          const u8   *kerning_data,
          size_t     kerning_data_size)
{
  size_t        i;
  render_info_t *rinfo;
  font_t        *font;

  /* allocate new font info */
  font = (font_t*)calloc(1, sizeof(font_t));
  if(font != NULL)
  {
    /* count number of render entries */
    rinfo = (render_info_t*)render_data;
    while((u8*)rinfo < render_data + render_data_size)
    {
      ++font->num_render_info;
      rinfo = next_render_info(rinfo);
    }

    /* allocate array of render info pointers */
    font->render_info = (render_info_t**)calloc(font->num_render_info, sizeof(render_info_t));
    if(font->render_info != NULL)
    {
      /* fill in the pointer list */
      rinfo = (render_info_t*)render_data;
      i     = 0;
      while((u8*)rinfo < render_data + render_data_size)
      {
        font->render_info[i++] = rinfo;
        rinfo = next_render_info(rinfo);
      }

      /* fill in the kerning info */
      font->kerning_info     = (kerning_info_t*)kerning_data;
      font->num_kerning_info = kerning_data_size / sizeof(kerning_info_t);

      /* set font size and name */
      font->pt   = pt;
      font->name = name;
    }
    else
    {
      /* failed to allocate render info list */
      free_font(font);
      font = NULL;
    }
  }

  return font;
}
Esempio n. 9
0
/*
** import_font()
** Try to import a given font.
*/
void import_font(cg_t *carta, ydom_node_t *node)
{
    struct stat st;
    cg_font_t *font;

    if (!(font = malloc0(sizeof(cg_font_t))))
        return ;
    font->id = ydom_node_get_attr_value(node, "id");
    font->outline = ydom_node_get_attr_value(node, "outline");
    font->metrics = ydom_node_get_attr_value(node, "metrics");
    if (!font->id || !font->outline || !font->metrics)
    {
        YLOG_ADD(YLOG_WARN, "Empty font declaration [line %d].",
                 node->line_nbr);
        free0(font->outline);
        free0(font->id);
        free0(font);
        return ;
    }
    font->f = -1;
    if (!stat(font->outline, &st) && !stat(font->metrics, &st))
    {
        yv_add(&carta->fonts, font);
        return ;
    }
    else
    {
        ystr_t ys1 = ys_new(""), ys2 = ys_new("");
        int i;
        for (i = 0; i < yv_len(carta->font_paths); ++i)
        {
            ys_printf(&ys1, "%s%c%s", carta->font_paths[i],
                      CARTA_SEP, font->outline);
            ys_printf(&ys2, "%s%c%s", carta->font_paths[i],
                      CARTA_SEP, font->metrics);
            if (!stat(ys1, &st) && !stat(ys2, &st))
            {
                free0(font->outline);
                free0(font->metrics);
                font->outline = ys_string(ys1);
                font->metrics = ys_string(ys2);
                yv_add(&carta->fonts, font);
                ys_del(&ys1);
                ys_del(&ys2);
                return ;
            }
        }
        ys_del(&ys1);
        ys_del(&ys2);
    }
    YLOG_ADD(YLOG_WARN, "Unable to find files '%s' and '%s' in font paths.",
             font->outline, font->metrics);
    free_font(font, NULL);
}
Esempio n. 10
0
void Font_Impl::load_font( GraphicContext &context, const FontDescription &desc, const std::string &filename )
{
	free_font();

	if (desc.get_subpixel())
	{
		glyph_cache.enable_subpixel = true;
		glyph_cache.anti_alias = true;	// Implies anti_alias is set
	}
	else
	{
		glyph_cache.enable_subpixel = false;
		glyph_cache.anti_alias = desc.get_anti_alias();
	}

#ifdef WIN32
	std::string path = PathHelp::get_fullpath(filename, PathHelp::path_type_file);
	std::string new_filename = PathHelp::get_filename(filename, PathHelp::path_type_file);
	FileSystem vfs(path);
	font_engine = new FontEngine_Win32(desc, new_filename, vfs);
	glyph_cache.font_metrics = font_engine->get_metrics();
#elif defined(__APPLE__)
    
    font_engine = new FontEngine_Cocoa(desc, filename);
    glyph_cache.font_metrics = font_engine->get_metrics();

#else
	std::string font_file_path = filename;
	if (font_file_path.empty())
	{
	    // Obtain the best matching font file from fontconfig.
		FontConfig &fc = FontConfig::instance();
		font_file_path = fc.match_font(desc);
	}

	std::string path = PathHelp::get_fullpath(font_file_path, PathHelp::path_type_file);
	std::string new_filename = PathHelp::get_filename(font_file_path, PathHelp::path_type_file);
	FileSystem vfs(path);
	IODevice io_dev = vfs.open_file(new_filename);

	int average_width = desc.get_average_width();
	int height = desc.get_height();

	// Ensure width and height are positive
	if (average_width < 0) average_width =-average_width;
	if (height < 0) height =-height;

	font_engine = new FontEngine_Freetype(io_dev, average_width, height);

	glyph_cache.font_metrics = font_engine->get_metrics();

#endif
}
Esempio n. 11
0
/*! deinitialize console subsystem */
void
console_exit(void)
{
  int i;

  /* free the font info */
  for(i = 0; i < num_fonts; ++i)
    free_font(fonts[i]);

  /* free the font info list */
  free(fonts);
  fonts = NULL;
}
Esempio n. 12
0
static duk_ret_t
js_new_Font(duk_context* ctx)
{
	const char* filename;
	font_t*     font;

	filename = duk_require_path(ctx, 0, NULL, false);
	font = load_font(filename);
	if (font == NULL)
		duk_error_ni(ctx, -1, DUK_ERR_ERROR, "Font(): unable to load font file `%s`", filename);
	duk_push_sphere_font(ctx, font);
	free_font(font);
	return 1;
}
Esempio n. 13
0
static duk_ret_t
js_LoadFont(duk_context* ctx)
{
	const char* filename = duk_require_string(ctx, 0);
	
	font_t* font;
	
	char* path = get_asset_path(filename, "fonts", false);
	font = load_font(path);
	free(path);
	if (font == NULL)
		duk_error_ni(ctx, -1, DUK_ERR_ERROR, "LoadFont(): Failed to load font file '%s'", filename);
	duk_push_sphere_font(ctx, font);
	free_font(font);
	return 1;
}
void CL_FontProvider_Freetype::load_font(const CL_FontDescription &desc, CL_IODevice &io_dev)
{
	free_font();

	if (desc.get_subpixel())
	{
		glyph_cache.enable_subpixel = true;
		glyph_cache.anti_alias = true;	// Implies anti_alias is set
	}
	else
	{
		glyph_cache.enable_subpixel = false;
		glyph_cache.anti_alias = desc.get_anti_alias();
	}

	// Load font from the opened file.
	font_engine = new CL_FontEngine_Freetype(io_dev, desc.get_height(), desc.get_average_width());

	glyph_cache.font_metrics = font_engine->get_metrics();
}
Esempio n. 15
0
void
gui_core_display_about_dialog(const gchar *desc,
			      const gchar *abouttext,
			      const gchar *modname)
{
	GtkWidget *aboutbox; //-- pointer to about dialog
	GString *str = g_string_new(NULL);
	GString *description = g_string_new(NULL);
	GString *text = g_string_new(NULL);
	GString *html_start = g_string_new(NULL);

	static const char *html_end = "</font></body></html>";
	MOD_FONT *mf = get_font(modname);
	g_string_printf(html_start,
			"<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"></head><body bgcolor=\"%s\" text=\"%s\"><font face=\"%s\" size=\"%+d\">",
			settings.bible_bg_color,
			settings.bible_text_color,
			((mf->old_font) ? mf->old_font : ""),
			mf->old_font_size_value - 1);
	free_font(mf);

	g_string_printf(description,
			"<center><font color=\"#000fcf\"><br/><b>%s</b></font></center><br/><hr width=\"80%%\"/><br/>",
			(desc ? desc : "No module present"));
	aboutbox = gui_create_about_modules();
	gtk_widget_show(aboutbox);

	about_module_display(str, abouttext, FALSE);

	g_string_append(text, html_start->str);
	g_string_append(text, description->str);
	g_string_append(text, str->str);
	g_string_append(text, html_end);
	HtmlOutput(text->str, text_html, NULL, NULL);

	g_string_free(text, TRUE);
	g_string_free(str, TRUE);
	g_string_free(description, TRUE);
	g_string_free(html_start, TRUE);
}
Esempio n. 16
0
void Font_Impl::load_font( GraphicContext &context, const FontDescription &desc, const std::string &filename, FileSystem &fs)
{
	free_font();

	if (desc.get_subpixel())
	{
		glyph_cache.enable_subpixel = true;
		glyph_cache.anti_alias = true;	// Implies anti_alias is set
	}
	else
	{
		glyph_cache.enable_subpixel = false;
		glyph_cache.anti_alias = desc.get_anti_alias();
	}

#ifdef WIN32
	font_engine = new FontEngine_Win32(desc, filename, fs);
	glyph_cache.font_metrics = font_engine->get_metrics();
    
#elif defined(__APPLE__)
    
    font_engine = new FontEngine_Cocoa(desc, filename);
    glyph_cache.font_metrics = font_engine->get_metrics();

#else
	IODevice io_dev = fs.open_file(filename);

	int average_width = desc.get_average_width();
	int height = desc.get_height();

	// Ensure width and height are positive
	if (average_width < 0) average_width =-average_width;
	if (height < 0) height =-height;

	font_engine = new FontEngine_Freetype(io_dev, average_width, height);

	glyph_cache.font_metrics = font_engine->get_metrics();

#endif
}
Esempio n. 17
0
NewFont::~NewFont() {
	if (font) {
		free_font(font);
	}
}
Esempio n. 18
0
/* Load a font and add it to the beginning of the global font list.
   Returns 0 upon success, nonzero upon failure.  */
grub_font_t
grub_font_load (const char *filename)
{
  grub_file_t file = 0;
  struct font_file_section section;
  char magic[4];
  grub_font_t font = 0;

#if FONT_DEBUG >= 1
  grub_dprintf ("font", "add_font(%s)\n", filename);
#endif

  if (filename[0] == '(' || filename[0] == '/' || filename[0] == '+')
    file = grub_buffile_open (filename, 1024);
  else
    {
      const char *prefix = grub_env_get ("prefix");
      char *fullname, *ptr;
      if (!prefix)
	{
	  grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"),
		      "prefix");
	  goto fail;
	}
      fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1
			      + sizeof ("/fonts/") + sizeof (".pf2"));
      if (!fullname)
	goto fail;
      ptr = grub_stpcpy (fullname, prefix);
      ptr = grub_stpcpy (ptr, "/fonts/");
      ptr = grub_stpcpy (ptr, filename);
      ptr = grub_stpcpy (ptr, ".pf2");
      *ptr = 0;
      file = grub_buffile_open (fullname, 1024);
      grub_free (fullname);
    }
  if (!file)
    goto fail;

#if FONT_DEBUG >= 3
  grub_dprintf ("font", "file opened\n");
#endif

  /* Read the FILE section.  It indicates the file format.  */
  if (open_section (file, &section) != 0)
    goto fail;

#if FONT_DEBUG >= 3
  grub_dprintf ("font", "opened FILE section\n");
#endif
  if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FILE,
		   sizeof (FONT_FORMAT_SECTION_NAMES_FILE) - 1) != 0)
    {
      grub_error (GRUB_ERR_BAD_FONT,
		  "font file format error: 1st section must be FILE");
      goto fail;
    }

#if FONT_DEBUG >= 3
  grub_dprintf ("font", "section name ok\n");
#endif
  if (section.length != 4)
    {
      grub_error (GRUB_ERR_BAD_FONT,
		  "font file format error (file type ID length is %d "
		  "but should be 4)", section.length);
      goto fail;
    }

#if FONT_DEBUG >= 3
  grub_dprintf ("font", "section length ok\n");
#endif
  /* Check the file format type code.  */
  if (grub_file_read (file, magic, 4) != 4)
    goto fail;

#if FONT_DEBUG >= 3
  grub_dprintf ("font", "read magic ok\n");
#endif

  if (grub_memcmp (magic, FONT_FORMAT_PFF2_MAGIC, 4) != 0)
    {
      grub_error (GRUB_ERR_BAD_FONT, "invalid font magic %x %x %x %x",
		  magic[0], magic[1], magic[2], magic[3]);
      goto fail;
    }

#if FONT_DEBUG >= 3
  grub_dprintf ("font", "compare magic ok\n");
#endif

  /* Allocate the font object.  */
  font = (grub_font_t) grub_zalloc (sizeof (struct grub_font));
  if (!font)
    goto fail;

  font_init (font);
  font->file = file;

#if FONT_DEBUG >= 3
  grub_dprintf ("font", "allocate font ok; loading font info\n");
#endif

  /* Load the font information.  */
  while (1)
    {
      if (open_section (file, &section) != 0)
	{
	  if (section.eof)
	    break;		/* Done reading the font file.  */
	  else
	    goto fail;
	}

#if FONT_DEBUG >= 2
      grub_dprintf ("font", "opened section %c%c%c%c ok\n",
		   section.name[0], section.name[1],
		   section.name[2], section.name[3]);
#endif

      if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FONT_NAME,
		       sizeof (FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0)
	{
	  font->name = read_section_as_string (&section);
	  if (!font->name)
	    goto fail;
	}
      else if (grub_memcmp (section.name,
			    FONT_FORMAT_SECTION_NAMES_POINT_SIZE,
			    sizeof (FONT_FORMAT_SECTION_NAMES_POINT_SIZE) -
			    1) == 0)
	{
	  if (read_section_as_short (&section, &font->point_size) != 0)
	    goto fail;
	}
      else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_WEIGHT,
			    sizeof (FONT_FORMAT_SECTION_NAMES_WEIGHT) - 1)
	       == 0)
	{
	  char *wt;
	  wt = read_section_as_string (&section);
	  if (!wt)
	    continue;
	  /* Convert the weight string 'normal' or 'bold' into a number.  */
	  if (grub_strcmp (wt, "normal") == 0)
	    font->weight = FONT_WEIGHT_NORMAL;
	  else if (grub_strcmp (wt, "bold") == 0)
	    font->weight = FONT_WEIGHT_BOLD;
	  grub_free (wt);
	}
      else if (grub_memcmp (section.name,
			    FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH,
			    sizeof (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH)
			    - 1) == 0)
	{
	  if (read_section_as_short (&section, &font->max_char_width) != 0)
	    goto fail;
	}
      else if (grub_memcmp (section.name,
			    FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT,
			    sizeof (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT)
			    - 1) == 0)
	{
	  if (read_section_as_short (&section, &font->max_char_height) != 0)
	    goto fail;
	}
      else if (grub_memcmp (section.name,
			    FONT_FORMAT_SECTION_NAMES_ASCENT,
			    sizeof (FONT_FORMAT_SECTION_NAMES_ASCENT) - 1)
	       == 0)
	{
	  if (read_section_as_short (&section, &font->ascent) != 0)
	    goto fail;
	}
      else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DESCENT,
			    sizeof (FONT_FORMAT_SECTION_NAMES_DESCENT) - 1)
	       == 0)
	{
	  if (read_section_as_short (&section, &font->descent) != 0)
	    goto fail;
	}
      else if (grub_memcmp (section.name,
			    FONT_FORMAT_SECTION_NAMES_CHAR_INDEX,
			    sizeof (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) -
			    1) == 0)
	{
	  if (load_font_index (file, section.length, font) != 0)
	    goto fail;
	}
      else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DATA,
			    sizeof (FONT_FORMAT_SECTION_NAMES_DATA) - 1) == 0)
	{
	  /* When the DATA section marker is reached, we stop reading.  */
	  break;
	}
      else
	{
	  /* Unhandled section type, simply skip past it.  */
#if FONT_DEBUG >= 3
	  grub_dprintf ("font", "Unhandled section type, skipping.\n");
#endif
	  grub_off_t section_end = grub_file_tell (file) + section.length;
	  if ((int) grub_file_seek (file, section_end) == -1)
	    goto fail;
	}
    }

  if (!font->name)
    {
      grub_dprintf ("font", "Font has no name.\n");
      font->name = grub_strdup ("Unknown");
    }

#if FONT_DEBUG >= 1
  grub_dprintf ("font", "Loaded font `%s'.\n"
	       "Ascent=%d Descent=%d MaxW=%d MaxH=%d Number of characters=%d.\n",
	       font->name,
	       font->ascent, font->descent,
	       font->max_char_width, font->max_char_height, font->num_chars);
#endif

  if (font->max_char_width == 0
      || font->max_char_height == 0
      || font->num_chars == 0
      || font->char_index == 0 || font->ascent == 0 || font->descent == 0)
    {
      grub_error (GRUB_ERR_BAD_FONT,
		  "invalid font file: missing some required data");
      goto fail;
    }

  /* Add the font to the global font registry.  */
  if (register_font (font) != 0)
    goto fail;

  return font;

fail:
  if (file)
    grub_file_close (file);
  if (font)
    font->file = 0;

  free_font (font);
  return 0;
}
Esempio n. 19
0
Font_Impl::~Font_Impl()
{
	free_font();
}
Esempio n. 20
0
void Font_Impl::load_font( Canvas &canvas, Sprite &sprite, const std::string &glyph_list, int spacelen, bool monospace, const FontMetrics &metrics)
{
	free_font();
	font_engine = new FontEngine_Sprite();

	glyph_cache.anti_alias = true;
	glyph_cache.enable_subpixel = false;
	glyph_cache.font_metrics = metrics;

	const int length = StringHelp::utf8_length(glyph_list);

	if ((length > sprite.get_frame_count()) || (length == 0))
	{
		throw Exception(string_format("Font error: Letter characters: %1, Available font glyphs: %2", 
				length,
				sprite.get_frame_count()));
	}

	//If monospace font requested, find the width of the widest glyph
	//Then set the fixed_width var to that width
	//Also set space to that width, if unset
	int fixed_width = 0;
	if (monospace)
	{
		for (int i=0; i < length; ++i)
		{
			int glyph_width = sprite.get_frame_size(i).width;
			if (glyph_width > fixed_width)
				fixed_width = glyph_width;
		}
		
		if (spacelen)
			spacelen = fixed_width;
	}

	//If not monospace, and space width not specified, then use average width as space width
	else if (spacelen <= 0)
	{
		std::string::size_type space_pos = glyph_list.find(' ');
		
		if (space_pos != std::string::npos)
		{
			//If there is a character for space, then use it
			spacelen = sprite.get_frame_size((int)space_pos).width;
		}
		else
		{
			//Make the space size the average of all character sizes
			spacelen = 0;
			
			for (int pos = 0; pos < length; ++pos)
			{
				spacelen += sprite.get_frame_size((int)(pos)).width;
			}
			
			spacelen /= length;
		}
	}
	
	int height = 0;
	for (int i=0; i < length; ++i)
	{
		int glyph_height = sprite.get_frame_size(i).height;
		if (glyph_height > height)
			height = glyph_height;
	}
	
	// Setup char to glyph map:

	UTF8_Reader reader(glyph_list.data(), glyph_list.length());
	int sprite_index = 0;
	while(!reader.is_end())
	{
		unsigned int glyph = reader.get_char();
		reader.next();
		
		const Sprite_Impl::SpriteFrame &sprite_frame = sprite.impl->frames[sprite_index];

		Subtexture sub_texture(sprite_frame.texture, sprite_frame.position);

		Point increment;
		if (fixed_width)
		{
			increment.x = fixed_width;
		}
		else
		{
			increment.x = sprite_frame.position.get_width();
		}
		Point offset(sprite_frame.offset);
		offset.y -= glyph_cache.font_metrics.get_ascent();

		glyph_cache.insert_glyph(canvas, glyph, sub_texture, offset, increment);

		sprite_index++;
	}

	// Did the glyphs not contain a space?
	std::string::size_type space_pos = glyph_list.find(' ');
	if (space_pos == std::string::npos)
	{
		FontPixelBuffer pb;
		pb.empty_buffer = true;
		pb.increment.x = spacelen;
		pb.glyph = ' ';
		glyph_cache.insert_glyph(canvas, pb);

	}

	float average_character_width=0.0f;
	float max_character_width=0.0f;

	if (monospace)
	{
		average_character_width = fixed_width;
		max_character_width = fixed_width;
	}
	else
	{
		for (int i=0; i < length; ++i)
		{
			int glyph_width = sprite.get_frame_size(i).width;
			average_character_width += glyph_width;
			if (glyph_width > max_character_width)
				max_character_width = glyph_width;
		}
		if (length)
			average_character_width /= length;

	}
	if (glyph_cache.font_metrics.get_max_character_width() == 0.0f)
	{
		glyph_cache.font_metrics.set_max_character_width(max_character_width);
	}
	if (glyph_cache.font_metrics.get_average_character_width() == 0.0f)
	{
		glyph_cache.font_metrics.set_average_character_width(average_character_width);
	}
	if (glyph_cache.font_metrics.get_height() == 0)
	{
		glyph_cache.font_metrics.set_height(height);
	}
}
CL_FontProvider_Freetype::~CL_FontProvider_Freetype()
{
	free_font();
}