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; }
/* * 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; }
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); } } }
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); }