From ab37394d087be634a63985171b760703d293cb84 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Wed, 2 Sep 2020 15:27:34 +0200 Subject: [PATCH] Flatten rectangles with integer precision Rectangles might be a little off, but is a lot faster if processing 100s of rectangles. --- zathura/utils.c | 70 +++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/zathura/utils.c b/zathura/utils.c index 5ceecaa..b4b058f 100644 --- a/zathura/utils.c +++ b/zathura/utils.c @@ -313,8 +313,8 @@ running_under_wsl(void) typedef struct zathura_point_s { - double x; - double y; + unsigned int x; + unsigned int y; } zathura_point_t; static int @@ -322,13 +322,31 @@ cmp_point(const void* va, const void* vb) { const zathura_point_t* a = va; const zathura_point_t* b = vb; - return a->x == b->x && a->y == b->y ? 0 : -1; + if (a->x == b->x) { + if (a->y == b->y) { + return 0; + } + + return a->y < b->y ? -1 : 1; + } + + return a->x < b->x ? -1 : 1; +} + +static unsigned int +ufloor(double f) { + return floor(f); +} + +static unsigned int +uceil(double f) { + return ceil(f); } static int -cmp_double(const void* vx, const void* vy) { - const double* x = vx; - const double* y = vy; +cmp_uint(const void* vx, const void* vy) { + const unsigned int* x = vx; + const unsigned int* y = vy; return *x == *y ? 0 : (*x > *y ? 1 : -1); } @@ -338,8 +356,8 @@ cmp_rectangle(const void* vr1, const void* vr2) { const zathura_rectangle_t* r1 = vr1; const zathura_rectangle_t* r2 = vr2; - return (r1->x1 == r2->x1 && r1->x2 == r2->x2 && r1->y1 == r2->y1 && - r1->y2 == r2->y2) + return (ufloor(r1->x1) == ufloor(r2->x1) && uceil(r1->x2) == uceil(r2->x2) && + ufloor(r1->y1) == ufloor(r2->y1) && uceil(r1->y2) == uceil(r2->y2)) ? 0 : -1; } @@ -356,7 +374,7 @@ girara_list_append_unique(girara_list_t* l, girara_compare_function_t cmp, void* } static void -append_unique_point(girara_list_t* list, const double x, const double y) { +append_unique_point(girara_list_t* list, const unsigned int x, const unsigned int y) { zathura_point_t* p = g_try_malloc(sizeof(zathura_point_t)); if (p == NULL) { return; @@ -375,22 +393,22 @@ rectangle_to_points(void* vrect, void* vlist) { const zathura_rectangle_t* rect = vrect; girara_list_t* list = vlist; - append_unique_point(list, rect->x1, rect->y1); - append_unique_point(list, rect->x1, rect->y2); - append_unique_point(list, rect->x2, rect->y1); - append_unique_point(list, rect->x2, rect->y2); + append_unique_point(list, ufloor(rect->x1), ufloor(rect->y1)); + append_unique_point(list, ufloor(rect->x1), uceil(rect->y2)); + append_unique_point(list, uceil(rect->x2), ufloor(rect->y1)); + append_unique_point(list, uceil(rect->x2), uceil(rect->y2)); } static void -append_unique_double(girara_list_t* list, const double v) { - double* p = g_try_malloc(sizeof(double)); +append_unique_uint(girara_list_t* list, const unsigned int v) { + double* p = g_try_malloc(sizeof(v)); if (p == NULL) { return; } *p = v; - if (girara_list_append_unique(list, cmp_double, p) == false) { + if (girara_list_append_unique(list, cmp_uint, p) == false) { g_free(p); } } @@ -399,24 +417,24 @@ append_unique_double(girara_list_t* list, const double v) { static void cut_rectangle(const zathura_rectangle_t* rect, girara_list_t* points, girara_list_t* rectangles) { // Lists of ordred relevant points - girara_list_t* xs = girara_sorted_list_new2(cmp_double, g_free); - girara_list_t* ys = girara_sorted_list_new2(cmp_double, g_free); + girara_list_t* xs = girara_sorted_list_new2(cmp_uint, g_free); + girara_list_t* ys = girara_sorted_list_new2(cmp_uint, g_free); - append_unique_double(xs, rect->x2); - append_unique_double(ys, rect->y2); + append_unique_uint(xs, uceil(rect->x2)); + append_unique_uint(ys, uceil(rect->y2)); GIRARA_LIST_FOREACH(points, zathura_point_t*, i_pt, pt) - if (pt->x > rect->x1 && pt->x < rect->x2) { - append_unique_double(xs, pt->x); + if (pt->x > ufloor(rect->x1) && pt->x < uceil(rect->x2)) { + append_unique_uint(xs, pt->x); } - if (pt->y > rect->y1 && pt->y < rect->y2) { - append_unique_double(ys, pt->y); + if (pt->y > ufloor(rect->y1) && pt->y < uceil(rect->y2)) { + append_unique_uint(ys, pt->y); } GIRARA_LIST_FOREACH_END(points, zathura_point_t*, i_pt, pt); - double x = rect->x1; + double x = ufloor(rect->x1); GIRARA_LIST_FOREACH(xs, const double*, ix, cx) - double y = rect->y1; + double y = ufloor(rect->y1); GIRARA_LIST_FOREACH(ys, const double*, iy, cy) zathura_rectangle_t* r = g_try_malloc(sizeof(zathura_rectangle_t)); *r = (zathura_rectangle_t) {x, y, *cx, *cy};