Esempio n. 1
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);
	}
}
Esempio n. 2
0
	void FontFamily_Impl::font_face_load(Canvas &canvas, Sprite &sprite, const std::string &glyph_list, float spacelen, bool monospace, const FontMetrics &metrics)
	{
		FontMetrics 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;
		}

		if (font_metrics.get_height() == 0)
		{
			font_metrics = FontMetrics(
				height,
				font_metrics.get_ascent(),
				font_metrics.get_descent(),
				font_metrics.get_internal_leading(),
				font_metrics.get_external_leading(),
				font_metrics.get_line_height());
		}

		FontDescription desc;
		desc.set_height(height);

		std::shared_ptr<FontEngine> engine = std::make_shared<FontEngine_Sprite>(desc, font_metrics);
		Font_Cache sprite_engine(engine);
		font_cache.push_back(sprite_engine);
		GlyphCache *glyph_cache = sprite_engine.glyph_cache.get();

		// 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];

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

			Sizef size = sprite_frame.position.get_size();

			Subtexture sub_texture(sprite_frame.texture, sprite_frame.position);
			glyph_cache->insert_glyph(canvas, glyph, sub_texture, offset, size, GlyphMetrics(Pointf(offset.x, offset.y), Sizef(increment.x, increment.y), Sizef(increment.x, increment.y)));

			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.metrics.advance.width = spacelen;
			pb.metrics.bbox_size.width = 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;

		}

	}