diff --git a/zathura/synctex.c b/zathura/synctex.c index 1fd4ac6..fb442ed 100644 --- a/zathura/synctex.c +++ b/zathura/synctex.c @@ -202,7 +202,10 @@ synctex_rectangles_from_position(const char* filename, const char* input_file, girara_list_free(other_rects); } - return hitlist; + girara_list_t* hitlist_flat = flatten_rectangles(hitlist); + girara_list_free(hitlist); + + return hitlist_flat; } #else bool diff --git a/zathura/utils.c b/zathura/utils.c index 4a66728..44a74db 100644 --- a/zathura/utils.c +++ b/zathura/utils.c @@ -310,3 +310,121 @@ running_under_wsl(void) free(content); return result; } + + + + + +typedef struct zathura_point_s +{ + double x; + double y; +} zathura_point_t; + +int cmp_point(const zathura_point_t* a, const zathura_point_t* b){ + return a->x == b->x && a->y == b->y ? 0 : -1; +} +int cmp_double(const double* x, const double* y){ + return *x == *y ? 0 : (*x > *y ? 1 : -1); +} +int cmp_rectangle(const zathura_rectangle_t* r1, const zathura_rectangle_t* r2){ + return + (r1->x1 == r2->x1 && + r1->x2 == r2->x2 && + r1->y1 == r2->y1 && + r1->y2 == r2->y2 + ) ? 0 : -1; +} +girara_compare_function_t gcmp_double = (girara_compare_function_t)cmp_double; +girara_compare_function_t gcmp_point = (girara_compare_function_t)cmp_point; +girara_compare_function_t gcmp_rectangle = (girara_compare_function_t)cmp_rectangle; + +bool girara_list_append_unique(girara_list_t* l, girara_compare_function_t cmp, void* item){ + if(girara_list_find(l, cmp, item)) + return false; + girara_list_append(l, item); + return true; +} + +void rectangle_to_points(const zathura_rectangle_t* rect, girara_list_t* list){ + zathura_point_t* p1 = g_try_malloc0(sizeof(zathura_point_t)); + zathura_point_t* p2 = g_try_malloc0(sizeof(zathura_point_t)); + zathura_point_t* p3 = g_try_malloc0(sizeof(zathura_point_t)); + zathura_point_t* p4 = g_try_malloc0(sizeof(zathura_point_t)); + if(p1==NULL || p2==NULL || p3==NULL || p4==NULL) + return; + *p1 = (zathura_point_t) { rect->x1, rect->y1 }; + *p2 = (zathura_point_t) { rect->x1, rect->y2 }; + *p3 = (zathura_point_t) { rect->x2, rect->y1 }; + *p4 = (zathura_point_t) { rect->x2, rect->y2 }; + if(!girara_list_append_unique(list, gcmp_point, (void*) p1)) + g_free(p1); + if(!girara_list_append_unique(list, gcmp_point, (void*) p2)) + g_free(p2); + if(!girara_list_append_unique(list, gcmp_point, (void*) p3)) + g_free(p3); + if(!girara_list_append_unique(list, gcmp_point, (void*) p4)) + g_free(p4); +} + +// transform a rectangle into multiple new ones according a grid of points +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(gcmp_double, g_free); + girara_list_t* ys = girara_sorted_list_new2(gcmp_double, g_free); + + double* rX2 = g_try_malloc(sizeof(double)); + double* rY2 = g_try_malloc(sizeof(double)); + if(rX2 == NULL || rY2 == NULL) + return; + + *rX2 = (double)rect->x2; + *rY2 = (double)rect->y2; + girara_list_append(xs, rX2); + girara_list_append(ys, rY2); + + GIRARA_LIST_FOREACH(points, zathura_point_t*, i_pt, pt) + if(pt->x > rect->x1 && pt->x < rect->x2){ + double* v = g_try_malloc(sizeof(double)); + if(v == NULL) return; + *v = (double) pt->x; + if(!girara_list_append_unique(xs, gcmp_double, v)) + g_free(v); + } + if(pt->y > rect->y1 && pt->y < rect->y2){ + double* v = g_try_malloc(sizeof(double)); + if(v == NULL) return; + *v = (double) pt->y; + if(!girara_list_append_unique(ys, gcmp_double, v)) + g_free(v); + } + GIRARA_LIST_FOREACH_END(points, zathura_point_t*, i_pt, pt); + + double x = rect->x1; + GIRARA_LIST_FOREACH(xs, double*, ix, cx) + double y = rect->y1; + GIRARA_LIST_FOREACH(ys, double*, iy, cy) + zathura_rectangle_t* r = g_try_malloc(sizeof(zathura_rectangle_t)); + *r = (zathura_rectangle_t) {x, y, *cx, *cy}; + y = *cy; + girara_list_append_unique(rectangles, gcmp_rectangle, r); + GIRARA_LIST_FOREACH_END(ys, double*, iy, cy); + x = *cx; + GIRARA_LIST_FOREACH_END(xs, double*, ix, cx); + + girara_list_free(xs); + girara_list_free(ys); +} + +girara_list_t* flatten_rectangles(girara_list_t* rectangles){ + girara_list_t* new_rectangles = girara_list_new2(g_free); + girara_list_t* points = girara_list_new2(g_free); + girara_list_foreach(rectangles, (girara_list_callback_t) rectangle_to_points, points); + + GIRARA_LIST_FOREACH(rectangles, zathura_rectangle_t*, i, r) + cut_rectangle(r, points, new_rectangles); + GIRARA_LIST_FOREACH_END(rectangles, zathura_rectangle_t*, i, r); + girara_list_free(points); + return new_rectangles; +} diff --git a/zathura/utils.h b/zathura/utils.h index eb0a52b..d8df39a 100644 --- a/zathura/utils.h +++ b/zathura/utils.h @@ -138,3 +138,5 @@ bool parse_color(GdkRGBA* color, const char* str); bool running_under_wsl(void); #endif // UTILS_H + +girara_list_t* flatten_rectangles(girara_list_t* rectangles);