Пример #1
0
static ssize_t sub_read(gp_io *io, void *buf, size_t size)
{
	struct sub_io *sub_io = GP_IO_PRIV(io);

	if (sub_io->cur > sub_io->end) {
		GP_BUG("Current offset (%zi) is after the end (%zi)",
		       sub_io->cur, sub_io->end);
		errno = EINVAL;
		return 0;
	}

	size_t io_size = sub_io->end - sub_io->cur;

	size = GP_MIN(size, io_size);

	if (size == 0)
		return 0;

	ssize_t ret = gp_io_read(sub_io->io, buf, size);

	if (ret < 0)
		return ret;

	sub_io->cur += ret;
	return ret;
}
Пример #2
0
static ssize_t mem_read(gp_io *io, void *buf, size_t size)
{
	struct mem_io *mem_io = GP_IO_PRIV(io);
	size_t rest = mem_io->size - mem_io->pos;
	ssize_t ret = GP_MIN(rest, size);

	if (ret <= 0) {
		errno = EIO;
		return 0;
	}

	memcpy(buf, mem_io->buf + mem_io->pos, ret);
	mem_io->pos += ret;

	return ret;
}
Пример #3
0
unsigned int gp_nr_threads(gp_size w, gp_size h, gp_progress_cb *callback)
{
	int count, threads;
	char *env;

	/* Try to override nr_threads from the callback first */
	if (callback != NULL && callback->threads) {
		GP_DEBUG(1, "Overriding nr_threads from callback to %i",
		         callback->threads);
		nr_threads = callback->threads;
	} else {
		/* Then try to override it from the enviroment variable */
		env = getenv("GP_THREADS");

		if (env) {
			nr_threads = atoi(env);
			GP_DEBUG(1, "Using GP_THREADS=%u from enviroment "
			            "variable", nr_threads);
		}
	}

	if (nr_threads == 0) {
		count = sysconf(_SC_NPROCESSORS_ONLN);
		GP_DEBUG(1, "Found %i CPUs", count);
	} else {
		count = nr_threads;
		GP_DEBUG(1, "Using nr_threads=%i", count);
	}

	threads = GP_MIN(count, (int)(w * h / 1024) + 1);

	/* Call to the sysconf may return -1 if unsupported */
	if (threads < -1)
		threads = 1;

	GP_DEBUG(1, "Max threads %i image size %ux%u runnig %u threads",
	         count, w, h, threads);

	return threads;
}
Пример #4
0
void GP_FillPolygon_Raw(GP_Context *context, unsigned int nvert,
                        const GP_Coord *xy, GP_Pixel pixel)
{
	unsigned int i;
	struct GP_Edge *e;

	if (nvert < 3)
		return;		/* not enough vertices */

	GP_Point const *vert = (GP_Point const *) xy;

	/* find first and last scanline */
	GP_Coord ymin = INT_MAX, ymax = -INT_MAX;
	for (i = 0; i < nvert; i++) {
		ymax = GP_MAX(ymax, vert[i].y);
		ymin = GP_MIN(ymin, vert[i].y);
	}

	/* build a list of edges */
	struct GP_Edge edges[nvert];
	unsigned int nedges = 0;		/* number of edges in list */
	for (i = 0; i < nvert; i++) {

		/*
		 * next vertex index (wraps to 0 at end to connect
		 * the last vertex with the first one)
		 */
		unsigned int nexti = (i+1) % nvert;

		/* add new edge record */
		e = edges + nedges++;
		GP_InitEdge(e, vert[i], vert[nexti]);
	}

	if (nedges < 2)
		return;		/* not really a polygon */

	/* initially sort edges by Y, then X */
	qsort(edges, nedges, sizeof(struct GP_Edge),
	      (GP_SortCallback) GP_CompareEdgesInitial);

	/*
	 * for each scanline, compute intersections with all edges
	 * and draw a horizontal line segment between the intersections.
	 */
	float inter[nedges];
	unsigned int ninter;
	int y;
	for (y = ymin; y <= ymax; y++) {

		/* mark edges we have just reached as active */
		for (i = 0; i < nedges; i++) {
			e = edges + i;
			if (e->state == EDGE_READY && (y == e->y)) {
				e->state = EDGE_ACTIVE;
			}
		}
		qsort(edges, nedges, sizeof(struct GP_Edge),
		      (GP_SortCallback) GP_CompareEdgesRuntime);

		/* record intersections with active edges */
		ninter = 0;
		for (i = 0; i < nedges; i++) {
			e = edges + i;
			if (e->state == EDGE_ACTIVE) {
				inter[ninter++] = e->x;
			}
		}

		/* draw each even range between intersections */
		for (i = 0; i < ninter; i += 2) {
			float start = inter[i];

			/* odd number of intersections - skip last */
			if (i+1 == ninter)
				break;

			float end = inter[i+1];
			GP_HLine_Raw(context, start, end, y, pixel);
		}

		/* update active edges for next step */
		for (i = 0; i < nedges; i++) {
			e = edges + i;
			if (e->state == EDGE_ACTIVE) {
				if (e->dy == 0) {
					e->state = EDGE_FINISHED;
				} else {
					e->x += e->dxy;
					e->dy--;
				}
			}
		}
	}

	/* finishing touch: draw all horizontal edges that were skipped
	 * in the main loop
	 */
	for (i = 0; i < nedges; i++) {
		e = edges + i;
		if (e->state == EDGE_HORIZONTAL) {
			GP_HLine_Raw(context, e->x, e->x + e->dxy, e->y,
				     pixel);
		}
	}
}
Пример #5
0
void GP_BlitXYXY_Clipped(const GP_Context *src,
                         GP_Coord x0, GP_Coord y0, GP_Coord x1, GP_Coord y1,
                         GP_Context *dst, GP_Coord x2, GP_Coord y2)
{
	/* Normalize source rectangle */
	if (x1 < x0)
		GP_SWAP(x0, x1);

	if (y1 < y0)
		GP_SWAP(y0, y1);

	/*
	 * Handle all cases where at least one of dest coordinates are out of
	 * the dest in positive direction -> src is out of dst completly.
	 */
	if (x2 >= (GP_Coord)GP_ContextW(dst) ||
	    y2 >= (GP_Coord)GP_ContextH(dst))
		return;

	/*
	 * The coordinates in dest are negative.
	 *
	 * We need to clip the source upper left corner accordingly.
	 *
	 * Notice that x2 and y2 are inside the dst rectangle now.
	 * (>= 0 and < w, < h)
	 */
	if (x2 < 0) {
		x0 -= x2;
		x2 = 0;
	}

	if (y2 < 0) {
		y0 -= y2;
		y2 = 0;
	}

	/* Make sure souce coordinates are inside of the src */
	x0 = GP_MAX(x0, 0);
	y0 = GP_MAX(y0, 0);
	x1 = GP_MIN(x1, (GP_Coord)GP_ContextW(src) - 1);
	y1 = GP_MIN(y1, (GP_Coord)GP_ContextH(src) - 1);

	/* And source rectangle fits inside of the destination */
	GP_Coord src_w = x1 - x0 + 1;
	GP_Coord src_h = y1 - y0 + 1;

	GP_Coord dst_w = GP_ContextW(dst) - x2;
	GP_Coord dst_h = GP_ContextH(dst) - y2;

	GP_DEBUG(2, "Blitting %ix%i, available %ix%i",
	         src_w, src_h, dst_w, dst_h);

	if (src_w > dst_w)
		x1 -= src_w - dst_w;

	if (src_h > dst_h)
		y1 -= src_h - dst_h;

	GP_DEBUG(2, "Blitting %ix%i->%ix%i in %ux%u to %ix%i in %ux%u",
	         x0, y0, x1, y1, GP_ContextW(src), GP_ContextH(src),
		 x2, y2, GP_ContextW(dst), GP_ContextH(dst));

	GP_BlitXYXY_Fast(src, x0, y0, x1, y1, dst, x2, y2);
}