Exemplo n.º 1
0
	GlyphMetrics GlyphCache::get_metrics(FontEngine *font_engine, const CanvasPtr &canvas, unsigned int glyph)
	{
		Font_TextureGlyph *gptr = get_glyph(canvas, font_engine, glyph);
		if (gptr)
		{
			return gptr->metrics;
		}
		return GlyphMetrics();
	}
Exemplo n.º 2
0
	GlyphMetrics Font::measure_text(Canvas &canvas, const std::string &string)
	{
		if (impl)
			return impl->measure_text(canvas, string);
		return GlyphMetrics();
	}
Exemplo n.º 3
0
	GlyphMetrics Font::get_metrics(Canvas &canvas, unsigned int glyph)
	{
		if (impl)
			return impl->get_metrics(canvas, glyph);
		return GlyphMetrics();
	}
Exemplo n.º 4
0
void Draw::DrawText(int x, int y, int angle, const wchar *text, Font font,
		            Color ink, int n, const int *dx)
{
#if defined(flagWINGL) || defined(flagLINUXGL)
	if(IsNull(ink))
		return;
	DrawTextOp(x, y, angle, text, font, ink, n, dx);
#else
	if(IsNull(ink)) return;
	if(n < 0)
		n = wstrlen(text);
	Std(font);
	double sina = 0;
	double cosa = 1;
	int    posx = 0;
	if(angle)
		Draw::SinCos(angle, sina, cosa);
	Font font0 = font;
	if(GetInfo() & DRAWTEXTLINES)
		font.Underline(false).Strikeout(false);
	for(int i = 0; i < n; i++) {
		wchar chr = text[i];
		GlyphInfo gi = GetGlyphInfo(font, chr);
		if(gi.IsNormal())
			if(angle)
				DrawTextOp(int(x + cosa * posx), int(y - sina * posx), angle, &chr, font, ink, 1, NULL);
			else {
				int c = 1;
				int dd = 0;
				while(i + c < n && c < 1000) {
					GlyphInfo gi2 = GetGlyphInfo(font, text[i + c]);
					if(!gi2.IsNormal())
						break;
					dd += dx ? dx[c - 1] : gi.width;
					c++;
					gi = gi2;
				}
				DrawTextOp(x + posx, y, 0, text + i, font, ink, c, dx);
				posx += dd;
				i += c - 1;
				if(dx)
					dx += c - 1;
			}
		else
		if(gi.IsReplaced()) {
			Font fnt = font;
			fnt.Face(gi.lspc);
			fnt.Height(gi.rspc);
			if(angle)
				DrawTextOp(int(x + cosa * posx), int(y - sina * (font.GetAscent() - fnt.GetAscent() + posx)),
				             angle, &chr, fnt, ink, 1, NULL);
			else
				DrawTextOp(x + posx, y + font.GetAscent() - fnt.GetAscent(), 0, &chr, fnt, ink, 1, NULL);
			GlyphMetrics(gi, font, chr);
		}
		else
		if(gi.IsComposed()) {
			ComposedGlyph cg;
			Compose(font, chr, cg);
			if(angle) {
				DrawTextOp(int(x + cosa * posx), int(y - sina * posx), angle, &cg.basic_char, font, ink, 1, NULL);
				DrawTextOp(int(x + cosa * (posx + cg.mark_pos.x)), int(y - sina * (cg.mark_pos.y + posx)), angle, &cg.mark_char, cg.mark_font, ink, 1, NULL);
			}
			else {
				DrawTextOp(x + posx, y, 0, &cg.basic_char, font, ink, 1, NULL);
				DrawTextOp(x + cg.mark_pos.x + posx, y + cg.mark_pos.y, 0, &cg.mark_char, cg.mark_font, ink, 1, NULL);
			}
			GlyphMetrics(gi, font, chr);
		}
		else {
			Font fnt = Arial(font.GetHeight());
			wchar chr = 0x25a1;
			gi = GetGlyphInfo(fnt, chr);
			if(!gi.IsNormal()) {
				chr = ' ';
				gi = GetGlyphInfo(fnt, chr);
			}
			if(angle)
				DrawTextOp(int(x + cosa * posx), int(y - sina * posx), angle, &chr, fnt, ink, 1, NULL);
			else
				DrawTextOp(x + posx, y, 0, &chr, fnt, ink, 1, NULL);
		}
		posx += dx ? *dx++ : gi.width;
	}

	if((GetInfo() & DRAWTEXTLINES) && (font0.IsUnderline() || font0.IsStrikeout())) {
		int hg = abs(font0.GetCy());
		if(hg == 0) hg = 10;
		int thickness = max(hg / 20, 1);

		int ascent = font0.GetAscent();
		Size offset = Point(0, ascent);
		if(angle) {
			offset.cx = fround(ascent * sina);
			offset.cy = fround(ascent * cosa);
		}

		x += offset.cx;
		y += offset.cy;
		if(font0.IsUnderline()) {
			int p = max(hg / 15, int(font0.Info().GetDescent() > 0));
			DrawLine(
				int(x + p * sina),
				int(y + p * cosa),
				int(x + posx * cosa + p * sina),
				int(y - posx * sina + p * cosa),
				thickness,
				ink
			);
		}
		if(font0.IsStrikeout()) {
			int p = -ascent / 3;
			DrawLine(
				int(x + p * sina),
				int(y + p * cosa),
				int(x + posx * cosa + p * sina),
				int(y - posx * sina + p * cosa),
				thickness,
				ink
			);
		}
	}

#endif
}
Exemplo n.º 5
0
void Draw::DrawText(int x, int y, int angle, const wchar *text, Font font,
		            Color ink, int n, const int *dx)
{
#ifdef flagWINGL
	if(IsNull(ink))
		return;
	DrawTextOp(x, y, angle, text, font, ink, n, dx);
#else
	if(IsNull(ink)) return;
	if(n < 0)
		n = wstrlen(text);
	Std(font);
	double sina;
	double cosa;
	int    d = 0;
	if(angle)
		Draw::SinCos(angle, sina, cosa);
	for(int i = 0; i < n; i++) {
		wchar chr = text[i];
		GlyphInfo gi = GetGlyphInfo(font, chr);
		if(gi.IsNormal())
			if(angle)
				DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &chr, font, ink, 1, NULL);
			else {
				int c = 1;
				int dd = 0;
				while(i + c < n) {
					GlyphInfo gi2 = GetGlyphInfo(font, text[i + c]);
					if(!gi2.IsNormal())
						break;
					dd += dx ? dx[c] : gi.width;
					c++;
					gi = gi2;
				}
				DrawTextOp(x + d, y, 0, text + i, font, ink, c, dx);
				d += dd;
				i += c - 1;
				if(dx)
					dx += c - 1;
			}
		else
		if(gi.IsReplaced()) {
			Font fnt = font;
			fnt.Face(gi.lspc);
			fnt.Height(gi.rspc);
			if(angle)
				DrawTextOp(int(x + cosa * d), int(y - sina * (font.GetAscent() - fnt.GetAscent() + d)),
				             angle, &chr, fnt, ink, 1, NULL);
			else
				DrawTextOp(x + d, y + font.GetAscent() - fnt.GetAscent(), 0, &chr, fnt, ink, 1, NULL);
			GlyphMetrics(gi, font, chr);
		}
		else
		if(gi.IsComposed()) {
			ComposedGlyph cg;
			Compose(font, chr, cg);
			if(angle) {
				DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &cg.basic_char, font, ink, 1, NULL);
				DrawTextOp(int(x + cosa * (d + cg.mark_pos.x)), int(y - sina * (cg.mark_pos.y + d)), angle, &cg.mark_char, cg.mark_font, ink, 1, NULL);
			}
			else {
				DrawTextOp(x + d, y, 0, &cg.basic_char, font, ink, 1, NULL);
				DrawTextOp(x + cg.mark_pos.x + d, y + cg.mark_pos.y, 0, &cg.mark_char, cg.mark_font, ink, 1, NULL);
			}
			GlyphMetrics(gi, font, chr);
		}
		else {
			Font fnt = Arial(font.GetHeight());
			wchar chr = 0x25a1;
			gi = GetGlyphInfo(fnt, chr);
			if(!gi.IsNormal()) {
				chr = ' ';
				gi = GetGlyphInfo(fnt, chr);
			}
			if(angle)
				DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &chr, fnt, ink, 1, NULL);
			else
				DrawTextOp(x + d, y, 0, &chr, fnt, ink, 1, NULL);
		}
		d += dx ? *dx++ : gi.width;
	}
#endif
}
Exemplo n.º 6
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;

		}

	}