예제 #1
0
int gp_progress_cb_mp(gp_progress_cb *self)
{
	struct gp_progress_cb_mp_priv *priv = self->priv;

	/*
	 * If any thread got non-zero return value from a callback abort all.
	 */
	if (priv->abort)
		return 1;

	if (pthread_mutex_trylock(&priv->mutex)) {
		GP_DEBUG(1, "Mutex locked, skipping calllback.");
		return 0;
	}

	/* Compute max value for the percentage */
	priv->orig_callback->percentage = GP_MAX(self->percentage, priv->max);
	priv->max = priv->orig_callback->percentage;

	/* Call the original callback */
	int ret = priv->orig_callback->callback(priv->orig_callback);

	/* Turn on abort flag if callback returned nonzero */
	if (ret)
		priv->abort = 1;

	pthread_mutex_unlock(&priv->mutex);

	return ret;
}
예제 #2
0
/*
 * Return maximal glyph advance for a character from str.
 */
static unsigned int max_glyph_advance_x(const GP_TextStyle *style,
                                        const char *str)
{
	unsigned int max = 0, i;

	for (i = 0; str[i] != '\0'; i++)
		max = GP_MAX(max, glyph_advance_x(style, str[i]));

	return max;
}
예제 #3
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);
		}
	}
}
예제 #4
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);
}