From 6ea27233227ee92afb21497a50f5224336f2489b Mon Sep 17 00:00:00 2001 From: Leandro Pereira Date: Mon, 17 Dec 2012 21:29:01 +0000 Subject: [PATCH] evas/common: Prepare soil to land polygon drawing code for threaded render SVN revision: 81187 --- src/lib/evas/common/evas_polygon.h | 1 + src/lib/evas/common/evas_polygon_main.c | 143 ++++++++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/src/lib/evas/common/evas_polygon.h b/src/lib/evas/common/evas_polygon.h index 0695f5427b..e30f76483b 100644 --- a/src/lib/evas/common/evas_polygon.h +++ b/src/lib/evas/common/evas_polygon.h @@ -8,6 +8,7 @@ EAPI RGBA_Polygon_Point *evas_common_polygon_point_add (RGBA_Polygon_Point *p EAPI RGBA_Polygon_Point *evas_common_polygon_points_clear (RGBA_Polygon_Point *points); EAPI void evas_common_polygon_draw (RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points, int x, int y); +EAPI void evas_common_polygon_rgba_draw (RGBA_Image *dst, int ext_x, int ext_y, int ext_w, int ext_h, DATA32 col, int render_op, RGBA_Polygon_Point *points, int x, int y); #endif /* _EVAS_POLYGON_H */ diff --git a/src/lib/evas/common/evas_polygon_main.c b/src/lib/evas/common/evas_polygon_main.c index f82d245149..8635d1c16c 100644 --- a/src/lib/evas/common/evas_polygon_main.c +++ b/src/lib/evas/common/evas_polygon_main.c @@ -310,3 +310,146 @@ evas_common_polygon_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Polygon_Po } } } + +EAPI void +evas_common_polygon_rgba_draw(RGBA_Image *dst, int ext_x, int ext_y, int ext_w, int ext_h, DATA32 col, int render_op, RGBA_Polygon_Point *points, int x, int y) +{ + RGBA_Gfx_Func func; + RGBA_Polygon_Point *pt; + RGBA_Vertex *point; + RGBA_Edge *edges; + Eina_Inlist *spans; + int num_active_edges; + int n; + int i, j, k; + int yy0, yy1, yi; + int *sorted_index; + + if ((ext_w <= 0) || (ext_h <= 0)) return; + + evas_common_cpu_end_opt(); + + n = 0; EINA_INLIST_FOREACH(points, pt) n++; + if (n < 3) return; + edges = malloc(sizeof(RGBA_Edge) * n); + if (!edges) return; + point = malloc(sizeof(RGBA_Vertex) * n); + if (!point) + { + free(edges); + return; + } + sorted_index = malloc(sizeof(int) * n); + if (!sorted_index) + { + free(edges); + free(point); + return; + } + + k = 0; + EINA_INLIST_FOREACH(points, pt) + { + point[k].x = pt->x + x; + point[k].y = pt->y + y; + point[k].i = k; + k++; + } + qsort(point, n, sizeof(RGBA_Vertex), polygon_point_sorter); + for (k = 0; k < n; k++) sorted_index[k] = point[k].i; + k = 0; + EINA_INLIST_FOREACH(points, pt) + { + point[k].x = pt->x + x; + point[k].y = pt->y + y; + point[k].i = k; + k++; + } + + yy0 = MAX(ext_y, ceil(point[sorted_index[0]].y - 0.5)); + yy1 = MIN(ext_y + ext_h - 1, floor(point[sorted_index[n - 1]].y - 0.5)); + + k = 0; + num_active_edges = 0; + spans = NULL; + + for (yi = yy0; yi <= yy1; yi++) + { + for (; (k < n) && (point[sorted_index[k]].y <= ((double)yi + 0.5)); k++) + { + i = sorted_index[k]; + + if (i > 0) j = i - 1; + else j = n - 1; + if (point[j].y <= ((double)yi - 0.5)) + { + POLY_EDGE_DEL(j) + } + else if (point[j].y > ((double)yi + 0.5)) + { + POLY_EDGE_ADD(j, yi) + } + if (i < (n - 1)) j = i + 1; + else j = 0; + if (point[j].y <= ((double)yi - 0.5)) + { + POLY_EDGE_DEL(i) + } + else if (point[j].y > ((double)yi + 0.5)) + { + POLY_EDGE_ADD(i, yi) + } + } + + qsort(edges, num_active_edges, sizeof(RGBA_Edge), polygon_edge_sorter); + + for (j = 0; j < num_active_edges; j += 2) + { + int x0, x1; + + x0 = ceil(edges[j].x - 0.5); + if (j < (num_active_edges - 1)) + x1 = floor(edges[j + 1].x - 0.5); + else + x1 = x0; + if ((x1 >= ext_x) && (x0 < (ext_x + ext_w)) && (x0 <= x1)) + { + RGBA_Span *span; + + if (x0 < ext_x) x0 = ext_x; + if (x1 >= (ext_x + ext_w)) x1 = ext_x + ext_w - 1; + span = malloc(sizeof(RGBA_Span)); + spans = eina_inlist_append(spans, EINA_INLIST_GET(span)); + span->y = yi; + span->x = x0; + span->w = (x1 - x0) + 1; + } + edges[j].x += edges[j].dx; + edges[j + 1].x += edges[j + 1].dx; + } + } + + free(edges); + free(point); + free(sorted_index); + + func = evas_common_gfx_func_composite_color_span_get(col, dst, 1, render_op); + if (spans) + { + RGBA_Span *span; + + EINA_INLIST_FOREACH(spans, span) + { + DATA32 *ptr; + + ptr = dst->image.data + (span->y * (dst->cache_entry.w)) + span->x; + func(NULL, NULL, col, ptr, span->w); + } + while (spans) + { + span = (RGBA_Span *)spans; + spans = eina_inlist_remove(spans, spans); + free(span); + } + } +}