Blame c++/contourgl/swrender.cpp

Ivan Mahonin 93cbac
/*
Ivan Mahonin 93cbac
    ......... 2015 Ivan Mahonin
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
    This program is free software: you can redistribute it and/or modify
Ivan Mahonin 93cbac
    it under the terms of the GNU General Public License as published by
Ivan Mahonin 93cbac
    the Free Software Foundation, either version 3 of the License, or
Ivan Mahonin 93cbac
    (at your option) any later version.
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
    This program is distributed in the hope that it will be useful,
Ivan Mahonin 93cbac
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Ivan Mahonin 93cbac
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Ivan Mahonin 93cbac
    GNU General Public License for more details.
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
    You should have received a copy of the GNU General Public License
Ivan Mahonin 93cbac
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
Ivan Mahonin 93cbac
*/
Ivan Mahonin 93cbac
Ivan Mahonin 572d9c
#include "swrender.h"
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
using namespace std;
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
Ivan Mahonin 572d9c
void SwRender::fill(
Ivan Mahonin 93cbac
	Surface &target,
Ivan Mahonin 93cbac
	const Color &color )
Ivan Mahonin 93cbac
{
Ivan Mahonin 93cbac
	for(Color *i = target.data, *end = i + target.count(); i != end; ++i)
Ivan Mahonin 93cbac
		*i = color;
Ivan Mahonin 93cbac
}
Ivan Mahonin 93cbac
Ivan Mahonin 572d9c
void SwRender::fill(
Ivan Mahonin 93cbac
	Surface &target,
Ivan Mahonin 93cbac
	const Color &color,
Ivan Mahonin 93cbac
	int left,
Ivan Mahonin 93cbac
	int top,
Ivan Mahonin 93cbac
	int width,
Ivan Mahonin 93cbac
	int height )
Ivan Mahonin 93cbac
{
Ivan Mahonin 93cbac
	int step = target.width - width;
Ivan Mahonin 93cbac
	for(Color *i = &target[top][left], *end = i + height*target.width; i < end; i += step)
Ivan Mahonin 93cbac
		for(Color *rowend = i + width; i < rowend; ++i)
Ivan Mahonin 93cbac
			*i = color;
Ivan Mahonin 93cbac
}
Ivan Mahonin 93cbac
Ivan Mahonin 572d9c
void SwRender::row(
Ivan Mahonin 93cbac
	Surface &target,
Ivan Mahonin 93cbac
	const Color &color,
Ivan Mahonin 93cbac
	int left,
Ivan Mahonin 93cbac
	int top,
Ivan Mahonin 93cbac
	int length )
Ivan Mahonin 93cbac
{
Ivan Mahonin 93cbac
	for(Color *i = &target[top][left], *end = i + length; i < end; ++i)
Ivan Mahonin 93cbac
		*i = color;
Ivan Mahonin 93cbac
}
Ivan Mahonin 93cbac
Ivan Mahonin 572d9c
void SwRender::row_alpha(
Ivan Mahonin 93cbac
	Surface &target,
Ivan Mahonin 93cbac
	const Color &color,
Ivan Mahonin 93cbac
	Color::type alpha,
Ivan Mahonin 93cbac
	int left,
Ivan Mahonin 93cbac
	int top,
Ivan Mahonin 93cbac
	int length )
Ivan Mahonin 93cbac
{
Ivan Mahonin 93cbac
	for(Color *i = &target[top][left], *end = i + length; i < end; ++i) {
Ivan Mahonin 9edf2e
		i->r = i->r*(1.f - alpha) + color.r*alpha;
Ivan Mahonin 9edf2e
		i->g = i->g*(1.f - alpha) + color.g*alpha;
Ivan Mahonin 9edf2e
		i->b = i->b*(1.f - alpha) + color.b*alpha;
Ivan Mahonin 9edf2e
		i->a = i->a*(1.f - alpha) + color.a*alpha;
Ivan Mahonin 93cbac
	}
Ivan Mahonin 93cbac
}
Ivan Mahonin 93cbac
Ivan Mahonin 572d9c
void SwRender::polyspan(
Ivan Mahonin 93cbac
	Surface &target,
Ivan Mahonin 93cbac
	const Polyspan &polyspan,
Ivan Mahonin 93cbac
	const Color &color,
Ivan Mahonin 93cbac
	bool evenodd,
Ivan Mahonin 93cbac
	bool invert )
Ivan Mahonin 93cbac
{
Ivan Mahonin 93cbac
	const ContextRect &window = polyspan.get_window();
Ivan Mahonin 93cbac
	const Polyspan::cover_array &covers = polyspan.get_covers();
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
	Polyspan::cover_array::const_iterator cur_mark = covers.begin();
Ivan Mahonin 93cbac
	Polyspan::cover_array::const_iterator end_mark = covers.end();
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
	Real cover = 0, area = 0, alpha = 0;
Ivan Mahonin 93cbac
	int	y = 0, x = 0;
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
	if (cur_mark == end_mark) {
Ivan Mahonin 93cbac
		// no marks at all
Ivan Mahonin 93cbac
		if (invert)
Ivan Mahonin 93cbac
			fill( target, color,
Ivan Mahonin 93cbac
				  window.minx, window.miny,
Ivan Mahonin 93cbac
				  window.maxx - window.minx, window.maxy - window.miny );
Ivan Mahonin 93cbac
		return;
Ivan Mahonin 93cbac
	}
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
	// fill initial rect / line
Ivan Mahonin 93cbac
	if (invert) {
Ivan Mahonin 93cbac
		// fill all the area above the first vertex
Ivan Mahonin 93cbac
		y = window.miny;
Ivan Mahonin 93cbac
		int l = window.maxx - window.minx;
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
		fill( target, color,
Ivan Mahonin 93cbac
			  window.minx, window.miny,
Ivan Mahonin 93cbac
			  l, cur_mark->y - window.miny );
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
		// fill the area to the left of the first vertex on that line
Ivan Mahonin 93cbac
		l = cur_mark->x - window.minx;
Ivan Mahonin 93cbac
		if (l)
Ivan Mahonin 93cbac
			row(target, color, window.minx, cur_mark->y, l);
Ivan Mahonin 93cbac
	}
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
	while(true) {
Ivan Mahonin 93cbac
		y = cur_mark->y;
Ivan Mahonin 93cbac
		x = cur_mark->x;
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
		area = cur_mark->area;
Ivan Mahonin 93cbac
		cover += cur_mark->cover;
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
		// accumulate for the current pixel
Ivan Mahonin 93cbac
		while(++cur_mark != covers.end()) {
Ivan Mahonin 93cbac
			if (y != cur_mark->y || x != cur_mark->x)
Ivan Mahonin 93cbac
				break;
Ivan Mahonin 93cbac
			area += cur_mark->area;
Ivan Mahonin 93cbac
			cover += cur_mark->cover;
Ivan Mahonin 93cbac
		}
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
		// draw pixel - based on covered area
Ivan Mahonin 93cbac
		if (area) { // if we're ok, draw the current pixel
Ivan Mahonin 93cbac
			alpha = polyspan.extract_alpha(cover - area, evenodd);
Ivan Mahonin 93cbac
			if (invert) alpha = 1 - alpha;
Ivan Mahonin 93cbac
			if (alpha) {
Ivan Mahonin 9edf2e
				Color::type a = (Color::type)alpha;
Ivan Mahonin 93cbac
				Color &c = target[y][x];
Ivan Mahonin 9edf2e
				c.r = c.r*(1.f - a) + color.r*a;
Ivan Mahonin 9edf2e
				c.g = c.g*(1.f - a) + color.g*a;
Ivan Mahonin 9edf2e
				c.b = c.b*(1.f - a) + color.b*a;
Ivan Mahonin 9edf2e
				c.a = c.a*(1.f - a) + color.a*a;
Ivan Mahonin 93cbac
			}
Ivan Mahonin 93cbac
			++x;
Ivan Mahonin 93cbac
		}
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
		// if we're done, don't use iterator and exit
Ivan Mahonin 93cbac
		if (cur_mark == end_mark)
Ivan Mahonin 93cbac
			break;
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
		// if there is no more live pixels on this line, goto next
Ivan Mahonin 93cbac
		if (y != cur_mark->y) {
Ivan Mahonin 93cbac
			if (invert) {
Ivan Mahonin 93cbac
				// fill the area at the end of the line
Ivan Mahonin 93cbac
				row(target, color, x, y, window.maxx - x);
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
				// fill area at the beginning of the next line
Ivan Mahonin 93cbac
				row(target, color, window.minx, cur_mark->y, cur_mark->x - window.minx);
Ivan Mahonin 93cbac
			}
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
			cover = 0;
Ivan Mahonin 93cbac
			continue;
Ivan Mahonin 93cbac
		}
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
		// draw span to next pixel - based on total amount of pixel cover
Ivan Mahonin 93cbac
		if (x < cur_mark->x) {
Ivan Mahonin 93cbac
			alpha = polyspan.extract_alpha(cover, evenodd);
Ivan Mahonin 93cbac
			if (invert) alpha = 1.0 - alpha;
Ivan Mahonin 93cbac
			if (alpha)
Ivan Mahonin 93cbac
				row_alpha(target, color, alpha, x, y, cur_mark->x - x);
Ivan Mahonin 93cbac
		}
Ivan Mahonin 93cbac
	}
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
	// fill the after stuff
Ivan Mahonin 93cbac
	if (invert) {
Ivan Mahonin 93cbac
		// fill the area at the end of the line
Ivan Mahonin 93cbac
		row(target, color, x, y, window.maxx - x);
Ivan Mahonin 93cbac
Ivan Mahonin 93cbac
		// fill area at the beginning of the next line
Ivan Mahonin 93cbac
		fill( target, color,
Ivan Mahonin 93cbac
			  window.minx, y+1,
Ivan Mahonin 93cbac
			  window.maxx - window.minx, window.maxy - y - 1 );
Ivan Mahonin 93cbac
	}
Ivan Mahonin 93cbac
}