void Interface::Draw(const Information &info, const Point &offset) const
{
	Point corner(Screen::Width() * position.X(), Screen::Height() * position.Y());
	corner += offset;
	
	for(const SpriteSpec &sprite : sprites)
	{
		if(!info.HasCondition(sprite.condition))
			continue;
		
		const Sprite *s = sprite.sprite;
		if(!s)
			s = info.GetSprite(sprite.name);
		if(!s)
			continue;
		
		Point offset(
			s->Width() * position.X(),
			s->Height() * position.Y());
		
		double zoom = 1.;
		if(sprite.size.X() && sprite.size.Y())
			zoom = min(1., min(sprite.size.X() / s->Width(), sprite.size.Y() / s->Height()));
		
		SpriteShader::Draw(s, sprite.position + corner - offset, zoom);
	}
	for(const SpriteSpec &outline : outlines)
	{
		if(!info.HasCondition(outline.condition))
			continue;
		
		const Sprite *s = outline.sprite;
		if(!s)
			s = info.GetSprite(outline.name);
		if(!s)
			continue;
		
		Point size(s->Width(), s->Height());
		if(outline.size.X() && outline.size.Y())
			size *= min(outline.size.X() / s->Width(), outline.size.Y() / s->Height());
		
		Point pos = outline.position + corner - outline.size * position;
		OutlineShader::Draw(s, pos, size,
			outline.isColored ? info.GetOutlineColor() : Color(1., 1.),
			info.GetSpriteUnit(outline.name));
	}
	
	double defaultAlign = position.X() + .5;
	for(const StringSpec &spec : labels)
	{
		if(!info.HasCondition(spec.condition) || !spec.color)
			continue;
		
		const string &str = spec.str;
		
		const Font &font = FontSet::Get(spec.size);
		double a = (spec.align >= 0.) ? spec.align : defaultAlign;
		Point align(font.Width(str) * a, 0.);
		font.Draw(str, corner - align + spec.position, *spec.color);
	}
	for(const StringSpec &spec : strings)
	{
		if(!info.HasCondition(spec.condition) || !spec.color)
			continue;
		
		const string &str = info.GetString(spec.str);
		
		const Font &font = FontSet::Get(spec.size);
		double a = (spec.align >= 0.) ? spec.align : defaultAlign;
		Point align(font.Width(str) * a, 0.);
		font.Draw(str, corner - align + spec.position, *spec.color);
	}
	
	for(const BarSpec &spec : bars)
	{
		if(!info.HasCondition(spec.condition) || !spec.color)
			continue;
		
		double length = spec.size.Length();
		if(!length || !spec.width)
			continue;
		
		double value = info.BarValue(spec.name);
		double segments = info.BarSegments(spec.name);
		if(!value)
			continue;
		
		// We will have (segments - 1) gaps between the segments.
		double empty = segments ? (spec.width / length) : 0.;
		double filled = segments ? (1. - empty * (segments - 1.)) / segments : 1.;
		
		double v = 0.;
		Point start = spec.position + corner;
		while(v < value)
		{
			Point from = start + v * spec.size;
			v += filled;
			Point to = start + min(v, value) * spec.size;
			v += empty;
			
			LineShader::Draw(from, to, spec.width, *spec.color);
		}
	}
	for(const BarSpec &spec : rings)
	{
		if(!info.HasCondition(spec.condition) || !spec.color)
			continue;
		
		if(!spec.size.X() || !spec.size.Y() || !spec.width)
			continue;
		
		double value = info.BarValue(spec.name);
		double segments = info.BarSegments(spec.name);
		if(!value)
			continue;
		if(segments <= 1.)
			segments = 0.;
		
		Point center = spec.position + corner - spec.size * position;
		RingShader::Draw(center, .5 * spec.size.X(), spec.width, value, *spec.color, segments);
	}
}