Blame c++/contourgl/test.cpp

93cbac
/*
93cbac
    ......... 2015 Ivan Mahonin
93cbac
93cbac
    This program is free software: you can redistribute it and/or modify
93cbac
    it under the terms of the GNU General Public License as published by
93cbac
    the Free Software Foundation, either version 3 of the License, or
93cbac
    (at your option) any later version.
93cbac
93cbac
    This program is distributed in the hope that it will be useful,
93cbac
    but WITHOUT ANY WARRANTY; without even the implied warranty of
93cbac
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
93cbac
    GNU General Public License for more details.
93cbac
93cbac
    You should have received a copy of the GNU General Public License
93cbac
    along with this program.  If not, see <http: licenses="" www.gnu.org="">.</http:>
93cbac
*/
93cbac
93cbac
#include <fstream></fstream>
93cbac
#include <iostream></iostream>
93cbac
93cbac
#include "test.h"
93cbac
#include "contourbuilder.h"
8cd87e
#include "triangulator.h"
49e693
#include "measure.h"
49e693
#include "utils.h"
d989ab
#include "clrender.h"
93cbac
93cbac
93cbac
using namespace std;
93cbac
93cbac
49e693
void Test::draw_contour(int start, int count, bool even_odd, bool invert, const Color &color) {
49e693
	glEnable(GL_STENCIL_TEST);
93cbac
49e693
	// render mask
49e693
	GLint draw_buffer;
49e693
	glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer);
49e693
	glDrawBuffer(GL_NONE);
49e693
	glClear(GL_STENCIL_BUFFER_BIT);
49e693
	glStencilFunc(GL_ALWAYS, 0, 0);
49e693
	if (even_odd) {
49e693
		glStencilOp(GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP);
93cbac
	} else {
49e693
		glStencilOpSeparate(GL_FRONT, GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP);
49e693
		glStencilOpSeparate(GL_BACK, GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP);
49e693
	}
49e693
	e.shaders.simple();
49e693
	glDrawArrays(GL_TRIANGLE_STRIP, start, count);
49e693
	glDrawBuffer((GLenum)draw_buffer);
49e693
49e693
	// fill mask
49e693
	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
49e693
	if (!even_odd && !invert)
49e693
		glStencilFunc(GL_NOTEQUAL, 0, -1);
49e693
	if (!even_odd &&  invert)
49e693
		glStencilFunc(GL_EQUAL, 0, -1);
49e693
	if ( even_odd && !invert)
49e693
		glStencilFunc(GL_EQUAL, 1, 1);
49e693
	if ( even_odd &&  invert)
49e693
		glStencilFunc(GL_EQUAL, 0, 1);
49e693
49e693
	e.shaders.color(color);
49e693
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
49e693
49e693
	glDisable(GL_STENCIL_TEST);
7c6b57
}
7c6b57
9edf2e
void Test::load(std::vector<contourinfo> &contours, const std::string &filename) {</contourinfo>
9edf2e
	vector<vector> groups;</vector>
9edf2e
	groups.push_back(Vector());
9edf2e
9edf2e
	ifstream f("data/contours.txt");
9edf2e
	int vertices_count = 0;
9edf2e
	while(f) {
9edf2e
		string s;
9edf2e
		f >> s;
9edf2e
		if (s == "g") {
9edf2e
			Vector t;
9edf2e
			f >> t.x >> t.y;
9edf2e
			groups.push_back(groups.back() + t);
9edf2e
		} else
9edf2e
		if (s == "end") {
9edf2e
			groups.pop_back();
9edf2e
			if ((int)groups.size() == 1)
9edf2e
				break;
9edf2e
		} else
9edf2e
		if (s == "path") {
9edf2e
			contours.push_back(ContourInfo());
9edf2e
			ContourInfo &ci = contours.back();
9edf2e
			f >> ci.invert
9edf2e
			  >> ci.antialias
9edf2e
			  >> ci.evenodd
9edf2e
			  >> ci.color.r
9edf2e
			  >> ci.color.g
9edf2e
			  >> ci.color.b
9edf2e
			  >> ci.color.a;
9edf2e
			bool closed = true;
9edf2e
			while(true) {
9edf2e
				f >> s;
9edf2e
				Vector p1;
9edf2e
				if (s == "M") {
9edf2e
					f >> p1.x >> p1.y;
9edf2e
					ci.contour.move_to(p1 + groups.back());
9edf2e
					closed = false;
9edf2e
				} else
9edf2e
				if (s == "L") {
9edf2e
					f >> p1.x >> p1.y;
9edf2e
					if (closed) {
9edf2e
						ci.contour.move_to(p1 + groups.back());
9edf2e
						closed = false;
9edf2e
					}
9edf2e
					ci.contour.line_to(p1 + groups.back());
9edf2e
				} else
9edf2e
				if (s == "Z") {
9edf2e
					ci.contour.close();
9edf2e
					closed = true;
9edf2e
				} else
9edf2e
				if (s == "end") {
9edf2e
					break;
9edf2e
				} else {
9edf2e
					cout << "bug " << s << endl;
9edf2e
					if (!f) break;
9edf2e
				}
9edf2e
			}
9edf2e
			if (!closed)
9edf2e
				ci.contour.close();
9edf2e
			if (ci.color.a < 0.9999)
9edf2e
				contours.pop_back();
9edf2e
			else
9edf2e
				vertices_count += ci.contour.get_chunks().size();
9edf2e
		} else
9edf2e
		if (s != "") {
9edf2e
			cout << "bug " << s << endl;
9edf2e
		}
9edf2e
	}
9edf2e
	if ((int)groups.size() != 1)
9edf2e
		cout << "bug groups " << groups.size() << endl;
9edf2e
9edf2e
	cout << contours.size() << " contours" << endl;
9edf2e
	cout << vertices_count << " vertices" << endl;
9edf2e
}
9edf2e
9edf2e
93cbac
void Test::test2() {
93cbac
	Contour c, cc;
93cbac
	ContourBuilder::build(cc);
93cbac
	cout << cc.get_chunks().size() << " commands" << endl;
93cbac
49e693
	Vector frame_size = Utils::get_frame_size();
831e90
93cbac
	Rect bounds;
93cbac
	bounds.p0 = Vector(-1.0, -1.0);
93cbac
	bounds.p1 = Vector( 1.0,  1.0);
831e90
	Vector min_size(1.75/frame_size.x, 1.75/frame_size.y);
93cbac
93cbac
	{
49e693
		Measure t("test_2_split");
93cbac
		cc.split(c, bounds, min_size);
93cbac
	}
93cbac
93cbac
	const Contour::ChunkList &chunks = c.get_chunks();
93cbac
	cout << chunks.size() << " vertices" << endl;
93cbac
7c6b57
	GLuint buffer_id = 0;
7c6b57
	GLuint array_id = 0;
8de121
	int count = 0;
a80036
	vector< vec2<float> > vertices;</float>
8de121
8de121
	{
49e693
		Measure t("test_2_init_buffer");
7c6b57
		vertices.resize(4+4*chunks.size());
7c6b57
		glGenBuffers(1, &buffer_id);
7c6b57
		glBindBuffer(GL_ARRAY_BUFFER, buffer_id);
8de121
		glBufferData( GL_ARRAY_BUFFER,
a80036
				      vertices.size()*sizeof(vec2<float>),</float>
8de121
					  &vertices.front(),
8de121
					  GL_DYNAMIC_DRAW );
8de121
		vertices.clear();
7c6b57
		vertices.reserve(4+4*chunks.size());
7c6b57
7c6b57
		glGenVertexArrays(1, &array_id);
7c6b57
		glBindVertexArray(array_id);
8de121
7c6b57
		glEnableVertexAttribArray(0);
7c6b57
		glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL);
7704aa
49e693
		e.shaders.color(Color(0.f, 0.f, 1.f, 1.f));
7c6b57
		glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size());
7c6b57
		glFinish();
a80036
		glClear(GL_COLOR_BUFFER_BIT);
a80036
		glFinish();
a80036
	}
8de121
8de121
	{
49e693
		Measure t("test_2_prepare_data");
7c6b57
		vertices.push_back(vec2<float>(bounds.p0.x, bounds.p0.y));</float>
7c6b57
		vertices.push_back(vec2<float>(bounds.p0.x, bounds.p1.y));</float>
7c6b57
		vertices.push_back(vec2<float>(bounds.p1.x, bounds.p0.y));</float>
7c6b57
		vertices.push_back(vec2<float>(bounds.p1.x, bounds.p1.y));</float>
a80036
		vertices.push_back(vec2<float>());</float>
a80036
		vertices.push_back(vec2<float>());</float>
8de121
		for(Contour::ChunkList::const_iterator i = chunks.begin(); i != chunks.end(); ++i) {
8de121
			if ( i->type == Contour::LINE
8de121
			  || i->type == Contour::CLOSE)
8de121
			{
a80036
				vertices.push_back(vec2<float>(i->p1));</float>
a80036
				vertices.push_back(vec2<float>(-1.f, (float)i->p1.y));</float>
8de121
			} else {
8de121
				vertices.push_back(vertices.back());
a80036
				vertices.push_back(vertices.back());
a80036
				vertices.push_back(vec2<float>(i->p1));</float>
a80036
				vertices.push_back(vertices.back());
8de121
			}
8de121
		}
7c6b57
		count = vertices.size() - 4;
8de121
	}
8de121
8de121
	{
49e693
		Measure t("test_2_send_data");
a80036
		glBufferSubData( GL_ARRAY_BUFFER,
a80036
						 0,
7c6b57
					     vertices.size()*sizeof(vertices.front()),
a80036
					     &vertices.front() );
8de121
	}
8de121
93cbac
	{
49e693
		Measure t("test_2_simple_fill.tga");
7c6b57
		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
93cbac
	}
93cbac
6e407d
	{
49e693
		Measure t("test_2_array.tga");
7c6b57
		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
7c6b57
		glDrawArrays(GL_TRIANGLE_STRIP, 4, count);
7c6b57
		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6e407d
	}
6e407d
93cbac
	{
49e693
		Measure t("test_2_contour_fill.tga");
49e693
		draw_contour(4, count, false, false, Color(0.f, 0.f, 1.f, 1.f));
93cbac
	}
93cbac
93cbac
	{
49e693
		Measure t("test_2_contour_fill_invert.tga");
49e693
		draw_contour(4, count, false, true, Color(0.f, 0.f, 1.f, 1.f));
93cbac
	}
93cbac
93cbac
	{
49e693
		Measure t("test_2_contour_evenodd.tga");
49e693
		draw_contour(4, count, true, false, Color(0.f, 0.f, 1.f, 1.f));
93cbac
	}
93cbac
93cbac
	{
49e693
		Measure t("test_2_contour_evenodd_invert.tga");
49e693
		draw_contour(4, count, true, true, Color(0.f, 0.f, 1.f, 1.f));
93cbac
	}
93cbac
a80036
	glBindBuffer(GL_ARRAY_BUFFER, 0);
7c6b57
	glDeleteBuffers(1, &buffer_id);
93cbac
}
93cbac
93cbac
void Test::test3() {
93cbac
	Contour c;
93cbac
	ContourBuilder::build(c);
93cbac
	cout << c.get_chunks().size() << " commands" << endl;
93cbac
49e693
	Vector frame_size = Utils::get_frame_size();
831e90
	int width = (int)frame_size.x;
831e90
	int height = (int)frame_size.y;
831e90
93cbac
	Rect bounds;
93cbac
	bounds.p0 = Vector(-1.0, -1.0);
93cbac
	bounds.p1 = Vector( 1.0,  1.0);
93cbac
	Rect pixel_bounds;
831e90
	pixel_bounds.p0 = Vector::zero();
831e90
	pixel_bounds.p1 = frame_size;
93cbac
93cbac
	c.transform(bounds, pixel_bounds);
93cbac
93cbac
	Polyspan polyspan;
831e90
	polyspan.init(0, 0, width, height);
93cbac
831e90
	Surface surface(width, height);
93cbac
	Color color(0.f, 0.f, 1.f, 1.f);
93cbac
93cbac
	{
49e693
		Measure t("test_3_build_polyspan");
93cbac
		c.to_polyspan(polyspan);
93cbac
	}
93cbac
93cbac
	cout << polyspan.get_covers().size() << " covers" << endl;
93cbac
93cbac
	glPushAttrib(GL_ALL_ATTRIB_BITS);
93cbac
	glColor4d(0.0, 0.0, 1.0, 1.0);
93cbac
	{
49e693
		Measure t("test_3_polyspan_gl_lines.tga");
93cbac
		glBegin(GL_LINE_STRIP);
93cbac
		for(Polyspan::cover_array::const_iterator i = polyspan.get_covers().begin(); i != polyspan.get_covers().end(); ++i)
93cbac
			glVertex2d((double)i->x/1024.0*2.0 - 1.0, (double)i->y/1024.0*2.0 - 1.0);
93cbac
		glEnd();
93cbac
	}
93cbac
	glPopAttrib();
93cbac
93cbac
93cbac
	{
49e693
		Measure t("test_3_polyspan_sort");
93cbac
		polyspan.sort_marks();
93cbac
	}
93cbac
93cbac
	{
49e693
		Measure t("test_3_polyspan_fill.tga", surface);
572d9c
		SwRender::polyspan(surface, polyspan, color, false, false);
93cbac
	}
93cbac
93cbac
	{
49e693
		Measure t("test_3_polyspan_fill_invert.tga", surface);
572d9c
		SwRender::polyspan(surface, polyspan, color, false, true);
93cbac
	}
93cbac
93cbac
	{
49e693
		Measure t("test_3_polyspan_evenodd.tga", surface);
572d9c
		SwRender::polyspan(surface, polyspan, color, true, false);
93cbac
	}
93cbac
93cbac
	{
49e693
		Measure t("test_3_polyspan_evenodd_invert.tga", surface);
572d9c
		SwRender::polyspan(surface, polyspan, color, true, true);
93cbac
	}
93cbac
}
93cbac
9edf2e
void Test::test4() {
49e693
	Vector frame_size = Utils::get_frame_size();
9edf2e
	int width = (int)frame_size.x;
9edf2e
	int height = (int)frame_size.y;
9edf2e
9edf2e
	Rect bounds_gl;
9edf2e
	bounds_gl.p0 = Vector(-1.0, -1.0);
9edf2e
	bounds_gl.p1 = Vector( 1.0,  1.0);
9edf2e
9edf2e
	Rect bounds_sw;
9edf2e
	bounds_sw.p0 = Vector();
9edf2e
	bounds_sw.p1 = frame_size;
9edf2e
9edf2e
	Rect bounds_file;
9edf2e
	bounds_file.p0 = Vector(0.0, 450.0);
9edf2e
	bounds_file.p1 = Vector(500.0, -50.0);
9edf2e
9edf2e
	vector<contourinfo> contours;</contourinfo>
9edf2e
	load(contours, "contours.txt");
9edf2e
9edf2e
	{
9edf2e
		// opengl
9edf2e
9edf2e
		vector<contourinfo> contours_gl = contours;</contourinfo>
9edf2e
		int commands_count = 0;
9edf2e
		for(vector<contourinfo>::iterator i = contours_gl.begin(); i != contours_gl.end(); ++i) {</contourinfo>
9edf2e
			i->contour.transform(bounds_file, bounds_gl);
9edf2e
			commands_count += i->contour.get_chunks().size();
9edf2e
		}
9edf2e
8cd87e
		// gl_stencil
8cd87e
9edf2e
		GLuint buffer_id = 0;
9edf2e
		GLuint array_id = 0;
9edf2e
		vector< vec2<float> > vertices;</float>
9edf2e
		vector<int> starts(contours_gl.size());</int>
9edf2e
		vector<int> counts(contours_gl.size());</int>
9edf2e
9edf2e
		{
49e693
			Measure t("test_4_gl_init_buffer");
9edf2e
			vertices.resize(4 + 4*commands_count + 2*contours_gl.size());
9edf2e
			glGenBuffers(1, &buffer_id);
9edf2e
			glBindBuffer(GL_ARRAY_BUFFER, buffer_id);
9edf2e
			glBufferData( GL_ARRAY_BUFFER,
9edf2e
						  vertices.size()*sizeof(vec2<float>),</float>
9edf2e
						  &vertices.front(),
9edf2e
						  GL_DYNAMIC_DRAW );
9edf2e
			vertices.clear();
9edf2e
			vertices.reserve(4 + 4*commands_count);
9edf2e
9edf2e
			glGenVertexArrays(1, &array_id);
9edf2e
			glBindVertexArray(array_id);
9edf2e
9edf2e
			glEnableVertexAttribArray(0);
9edf2e
			glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL);
9edf2e
49e693
			e.shaders.color(Color(0.f, 0.f, 1.f, 1.f));
9edf2e
			glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size());
9edf2e
			glFinish();
9edf2e
			glClear(GL_COLOR_BUFFER_BIT);
9edf2e
			glFinish();
9edf2e
		}
9edf2e
9edf2e
		{
49e693
			Measure t("test_4_gl_stencil_prepare_data");
9edf2e
			vertices.push_back(vec2<float>(bounds_gl.p0.x, bounds_gl.p0.y));</float>
9edf2e
			vertices.push_back(vec2<float>(bounds_gl.p0.x, bounds_gl.p1.y));</float>
9edf2e
			vertices.push_back(vec2<float>(bounds_gl.p1.x, bounds_gl.p0.y));</float>
9edf2e
			vertices.push_back(vec2<float>(bounds_gl.p1.x, bounds_gl.p1.y));</float>
9edf2e
			for(int i = 0; i < (int)contours_gl.size(); ++i) {
9edf2e
				starts[i] = (int)vertices.size();
9edf2e
				const Contour::ChunkList &chunks = contours_gl[i].contour.get_chunks();
9edf2e
				for(Contour::ChunkList::const_iterator j = chunks.begin(); j != chunks.end(); ++j) {
9edf2e
					if (j->type == Contour::LINE) {
9edf2e
						vertices.push_back(vec2<float>(j->p1));</float>
9edf2e
						vertices.push_back(vec2<float>(-1.f, (float)j->p1.y));</float>
9edf2e
					} else
9edf2e
					if (j->type == Contour::CLOSE) {
9edf2e
						vertices.push_back(vec2<float>(j->p1));</float>
9edf2e
						vertices.push_back(vec2<float>(-1.f, (float)j->p1.y));</float>
9edf2e
					} else {
9edf2e
						vertices.push_back(vertices.back());
9edf2e
						vertices.push_back(vec2<float>(j->p1));</float>
9edf2e
						vertices.push_back(vertices.back());
9edf2e
						vertices.push_back(vec2<float>(-1.f, (float)j->p1.y));</float>
9edf2e
					}
9edf2e
				}
9edf2e
				counts[i] = (int)vertices.size() - starts[i];
9edf2e
			}
9edf2e
		}
9edf2e
9edf2e
		{
49e693
			Measure t("test_4_gl_stencil_send_data");
9edf2e
			glBufferSubData( GL_ARRAY_BUFFER,
9edf2e
							 0,
9edf2e
						     vertices.size()*sizeof(vertices.front()),
9edf2e
						     &vertices.front() );
9edf2e
		}
9edf2e
9edf2e
		{
49e693
			Measure t("test_4_gl_stencil_points.tga");
8cd87e
			glDrawArrays(GL_POINTS, 0, vertices.size());
8cd87e
		}
8cd87e
8cd87e
		{
49e693
			Measure t("test_4_gl_stencil_render.tga");
9edf2e
			for(int i = 0; i < (int)contours_gl.size(); ++i) {
49e693
				draw_contour(
9edf2e
					starts[i],
9edf2e
					counts[i],
9edf2e
					contours_gl[i].invert,
9edf2e
					contours_gl[i].evenodd,
9edf2e
					contours_gl[i].color );
9edf2e
			}
9edf2e
			// glDrawArrays(GL_POINTS, 0, vertices.size());
9edf2e
		}
8cd87e
8cd87e
		// gl_triangles
8cd87e
8cd87e
		GLuint index_buffer_id = 0;
8cd87e
		vector<int> triangle_starts(contours_gl.size());</int>
8cd87e
		vector<int> triangle_counts(contours_gl.size());</int>
8cd87e
		vector<int> triangles;</int>
8cd87e
		vertices.clear();
8cd87e
		vertices.reserve(commands_count);
8cd87e
8cd87e
		{
49e693
			Measure t("test_4_gl_init_index_buffer");
8cd87e
			triangles.resize(3*commands_count);
8cd87e
			glGenBuffers(1, &index_buffer_id);
8cd87e
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_id);
8cd87e
			glBufferData( GL_ELEMENT_ARRAY_BUFFER,
8cd87e
						  triangles.size()*sizeof(triangles.front()),
8cd87e
						  &triangles.front(),
8cd87e
						  GL_DYNAMIC_DRAW );
8cd87e
			triangles.clear();
8cd87e
			triangles.reserve(3*commands_count);
8cd87e
		}
8cd87e
8cd87e
		{
49e693
			Measure t("test_4_gl_triangulate");
8cd87e
			int index_offset = 4;
8cd87e
			for(int i = 0; i < (int)contours_gl.size(); ++i) {
8cd87e
				triangle_starts[i] = (int)triangles.size();
8cd87e
				Triangulator::triangulate(contours_gl[i].contour, triangles, index_offset);
8cd87e
				triangle_counts[i] = (int)triangles.size() - triangle_starts[i];
8cd87e
				index_offset += (int)contours_gl[i].contour.get_chunks().size();
8cd87e
			}
8cd87e
		}
8cd87e
8cd87e
		cout << triangles.size() << " triangles" << endl;
8cd87e
8cd87e
		{
49e693
			Measure t("test_4_gl_triangles_prepare_vertices");
8cd87e
			for(int i = 0; i < (int)contours_gl.size(); ++i) {
8cd87e
				const Contour::ChunkList &chunks = contours_gl[i].contour.get_chunks();
8cd87e
				for(Contour::ChunkList::const_iterator j = chunks.begin(); j != chunks.end(); ++j)
8cd87e
					vertices.push_back(vec2<float>(j->p1));</float>
8cd87e
			}
8cd87e
		}
8cd87e
8cd87e
		{
49e693
			Measure t("test_4_gl_triangles_send_data");
8cd87e
			glBufferSubData( GL_ARRAY_BUFFER,
8cd87e
							 4*sizeof(vertices.front()),
8cd87e
						     vertices.size()*sizeof(vertices.front()),
8cd87e
						     &vertices.front() );
8cd87e
			glBufferSubData( GL_ELEMENT_ARRAY_BUFFER,
8cd87e
							 0,
8cd87e
						     triangles.size()*sizeof(triangles.front()),
8cd87e
						     &triangles.front() );
8cd87e
		}
8cd87e
8cd87e
		{
49e693
			Measure t("test_4_gl_triangles_render.tga");
8cd87e
			for(int i = 0; i < (int)contours_gl.size(); ++i) {
49e693
				e.shaders.color(contours_gl[i].color);
8cd87e
				glDrawElements(GL_TRIANGLES, triangle_counts[i], GL_UNSIGNED_INT, (char*)NULL + triangle_starts[i]*sizeof(int));
8cd87e
			}
8cd87e
		}
9edf2e
	}
9edf2e
9edf2e
	{
9edf2e
		// software
9edf2e
9edf2e
		vector<contourinfo> contours_sw = contours;</contourinfo>
9edf2e
		for(vector<contourinfo>::iterator i = contours_sw.begin(); i != contours_sw.end(); ++i)</contourinfo>
9edf2e
			i->contour.transform(bounds_file, bounds_sw);
9edf2e
9edf2e
		vector<polyspan> polyspans(contours_sw.size());</polyspan>
9edf2e
		{
49e693
			Measure t("test_4_sw_build_polyspans");
9edf2e
			for(int i = 0; i < (int)contours_sw.size(); ++i) {
9edf2e
				polyspans[i].init(0, 0, width, height);
9edf2e
				contours_sw[i].contour.to_polyspan(polyspans[i]);
9edf2e
				polyspans[i].sort_marks();
9edf2e
			}
9edf2e
		}
9edf2e
9edf2e
		Surface surface(width, height);
9edf2e
9edf2e
		{
49e693
			Measure t("test_4_sw_render_polyspans.tga", surface);
9edf2e
			for(int i = 0; i < (int)contours_sw.size(); ++i)
572d9c
				SwRender::polyspan(surface, polyspans[i], contours_sw[i].color, contours_sw[i].evenodd, contours_sw[i].invert);
9edf2e
		}
9edf2e
	}
d989ab
d989ab
	{
d989ab
		// cl
d989ab
d989ab
		vector<contourinfo> contours_cl = contours;</contourinfo>
d989ab
		Surface surface(width+2, height+2);
d989ab
d989ab
		Measure t("test_4_cl.tga", surface);
d989ab
d989ab
		ClRender clr(e.cl);
d989ab
		clr.send_surface(&surface);
d989ab
		for(vector<contourinfo>::const_iterator i = contours_cl.begin(); i != contours_cl.end(); ++i)</contourinfo>
d989ab
			clr.contour(i->contour, bounds_file, i->color, i->invert, i->evenodd);
d989ab
		clr.receive_surface();
d989ab
	}
9edf2e
}