Use type cairo_region_t* for Fl_Region under Wayland platform

This commit is contained in:
ManoloFLTK 2024-03-20 15:20:31 +01:00
parent af90841fbc
commit 0fa49f0ab4
6 changed files with 31 additions and 57 deletions

View File

@ -49,7 +49,7 @@ typedef opaque Fl_Offscreen;
Pointer to a platform-specific structure representing a collection of rectangles. Pointer to a platform-specific structure representing a collection of rectangles.
\note This pointer can be safely cast to these types on each platform: \note This pointer can be safely cast to these types on each platform:
\li X11: Region as defined by X11 \li X11: Region as defined by X11
\li Wayland: struct flCairoRegion * \li Wayland: cairo_region_t *
\li Windows: HRGN \li Windows: HRGN
\li macOS: struct flCocoaRegion * \li macOS: struct flCocoaRegion *
*/ */

View File

@ -28,10 +28,6 @@ typedef struct _PangoLayout PangoLayout;
typedef struct _PangoContext PangoContext; typedef struct _PangoContext PangoContext;
typedef struct _PangoFontDescription PangoFontDescription; typedef struct _PangoFontDescription PangoFontDescription;
struct flCairoRegion {
int count;
struct _cairo_rectangle *rects;
}; // a region is the union of a series of rectangles
class Fl_Cairo_Font_Descriptor : public Fl_Font_Descriptor { class Fl_Cairo_Font_Descriptor : public Fl_Font_Descriptor {
public: public:

View File

@ -1396,41 +1396,19 @@ void Fl_Cairo_Graphics_Driver::text_extents(const char* txt, int n, int& dx, int
// //
Fl_Region Fl_Cairo_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) { Fl_Region Fl_Cairo_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) {
struct flCairoRegion *R = (struct flCairoRegion*)malloc(sizeof(*R)); cairo_rectangle_int_t rect = {x, y, w, h};
R->count = 1; return cairo_region_create_rectangle(&rect);
R->rects = (cairo_rectangle_t *)malloc(sizeof(cairo_rectangle_t));
R->rects->x=x, R->rects->y=y, R->rects->width=w; R->rects->height=h;
return (Fl_Region)R;
}
// r1 ⊂ r2
static bool CairoRectContainsRect(cairo_rectangle_t *r1, cairo_rectangle_t *r2) {
return r1->x >= r2->x && r1->y >= r2->y && r1->x+r1->width <= r2->x+r2->width &&
r1->y+r1->height <= r2->y+r2->height;
} }
void Fl_Cairo_Graphics_Driver::add_rectangle_to_region(Fl_Region r_, int X, int Y, int W, int H) { void Fl_Cairo_Graphics_Driver::add_rectangle_to_region(Fl_Region r_, int X, int Y, int W, int H) {
struct flCairoRegion *r = (struct flCairoRegion*)r_; cairo_rectangle_int_t rect = {X, Y, W, H};
cairo_rectangle_t arg = {double(X), double(Y), double(W), double(H)}; cairo_region_union_rectangle((cairo_region_t*)r_, &rect);
int j; // don't add a rectangle totally inside the Fl_Region
for (j = 0; j < r->count; j++) {
if (CairoRectContainsRect(&arg, &(r->rects[j]))) break;
}
if (j >= r->count) {
r->rects = (cairo_rectangle_t*)realloc(r->rects, (++(r->count)) * sizeof(cairo_rectangle_t));
r->rects[r->count - 1] = arg;
}
} }
void Fl_Cairo_Graphics_Driver::XDestroyRegion(Fl_Region r_) { void Fl_Cairo_Graphics_Driver::XDestroyRegion(Fl_Region r_) {
if (r_) { cairo_region_destroy((cairo_region_t*)r_);
struct flCairoRegion *r = (struct flCairoRegion*)r_;
free(r->rects);
free(r);
}
} }
#define fl_max(a,b) ((a) > (b) ? (a) : (b)) #define fl_max(a,b) ((a) > (b) ? (a) : (b))
@ -1440,27 +1418,24 @@ void Fl_Cairo_Graphics_Driver::restore_clip() {
if (cairo_) { if (cairo_) {
cairo_reset_clip(cairo_); cairo_reset_clip(cairo_);
// apply what's in rstack // apply what's in rstack
struct flCairoRegion *r = (struct flCairoRegion*)rstack[rstackptr]; cairo_region_t *r = (cairo_region_t*)rstack[rstackptr];
if (r) { if (r) {
if (!clip_) { if (!clip_) {
clip_ = new Clip(); clip_ = new Clip();
clip_->prev = NULL; clip_->prev = NULL;
} }
for (int i = 0; i < r->count; i++) { int count = cairo_region_num_rectangles(r);
cairo_rectangle(cairo_, r->rects[i].x - 0.5, r->rects[i].y - 0.5, r->rects[i].width, r->rects[i].height); cairo_rectangle_int_t rect;
// put in clip_ the bounding rect of region r for (int i = 0; i < count; i++) {
if (i == 0) { cairo_region_get_rectangle(r, i, &rect);
clip_->x = r->rects[0].x; clip_->y = r->rects[0].y; cairo_rectangle(cairo_, rect.x - 0.5, rect.y - 0.5, rect.width, rect.height);
clip_->w = r->rects[0].width; clip_->h = r->rects[0].height;
} else {
int R = fl_max(r->rects[i].x + r->rects[i].width, clip_->x + clip_->w);
int B = fl_max(r->rects[i].y + r->rects[i].height, clip_->y + clip_->h);
clip_->x = fl_min(r->rects[i].x, clip_->x) ;
clip_->y = fl_min(r->rects[i].y, clip_->y);
clip_->w = R - clip_->x;
clip_->h = B - clip_->y;
}
} }
// put in clip_ the bounding rect of region r
cairo_region_get_extents(r, &rect);
clip_->x = rect.x;
clip_->y = rect.y;
clip_->w = rect.width;
clip_->h = rect.height;
cairo_clip(cairo_); cairo_clip(cairo_);
} else if (clip_) { } else if (clip_) {
clip_->w = -1; clip_->w = -1;

View File

@ -60,7 +60,7 @@ public:
static struct wld_buffer *create_wld_buffer(int width, int height, bool with_shm = true); static struct wld_buffer *create_wld_buffer(int width, int height, bool with_shm = true);
static void create_shm_buffer(wld_buffer *buffer); static void create_shm_buffer(wld_buffer *buffer);
static void buffer_release(struct wld_window *window); static void buffer_release(struct wld_window *window);
static void buffer_commit(struct wld_window *window, struct flCairoRegion *r = NULL); static void buffer_commit(struct wld_window *window, cairo_region_t *r = NULL);
static void cairo_init(struct draw_buffer *buffer, int width, int height, int stride, static void cairo_init(struct draw_buffer *buffer, int width, int height, int stride,
cairo_format_t format); cairo_format_t format);
// used by class Fl_Wayland_Gl_Window_Driver // used by class Fl_Wayland_Gl_Window_Driver

View File

@ -22,7 +22,7 @@
#include <unistd.h> // for close() #include <unistd.h> // for close()
#include <errno.h> #include <errno.h>
#include <string.h> // for strerror() #include <string.h> // for strerror()
#include <cairo/cairo.h>
extern "C" { extern "C" {
# include "../../../libdecor/src/os-compatibility.h" // for libdecor_os_create_anonymous_file() # include "../../../libdecor/src/os-compatibility.h" // for libdecor_os_create_anonymous_file()
@ -139,15 +139,18 @@ const struct wl_callback_listener *Fl_Wayland_Graphics_Driver::p_surface_frame_l
// copy pixels in region r from the Cairo surface to the Wayland buffer // copy pixels in region r from the Cairo surface to the Wayland buffer
static void copy_region(struct wld_window *window, struct flCairoRegion *r) { static void copy_region(struct wld_window *window, cairo_region_t *r) {
struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer = window->buffer; struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer = window->buffer;
float f = Fl::screen_scale(window->fl_win->screen_num()) * float f = Fl::screen_scale(window->fl_win->screen_num()) *
Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale(); Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale();
for (int i = 0; i < r->count; i++) { int count = cairo_region_num_rectangles(r);
int left = r->rects[i].x * f; cairo_rectangle_int_t rect;
int top = r->rects[i].y * f; for (int i = 0; i < count; i++) {
int width = r->rects[i].width * f; cairo_region_get_rectangle(r, i, &rect);
int height = r->rects[i].height * f; int left = rect.x * f;
int top = rect.y * f;
int width = rect.width * f;
int height = rect.height * f;
int offset = top * buffer->draw_buffer.stride + 4 * left; int offset = top * buffer->draw_buffer.stride + 4 * left;
int W4 = 4 * width; int W4 = 4 * width;
for (int l = 0; l < height; l++) { for (int l = 0; l < height; l++) {
@ -163,7 +166,7 @@ static void copy_region(struct wld_window *window, struct flCairoRegion *r) {
} }
void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window, struct flCairoRegion *r) void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window, cairo_region_t *r)
{ {
if (!window->buffer->wl_buffer) create_shm_buffer(window->buffer); if (!window->buffer->wl_buffer) create_shm_buffer(window->buffer);
cairo_surface_t *surf = cairo_get_target(window->buffer->draw_buffer.cairo_); cairo_surface_t *surf = cairo_get_target(window->buffer->draw_buffer.cairo_);

View File

@ -408,7 +408,7 @@ void Fl_Wayland_Window_Driver::flush() {
if (!window || !window->configured_width) return; if (!window || !window->configured_width) return;
Fl_X *ip = Fl_X::flx(pWindow); Fl_X *ip = Fl_X::flx(pWindow);
struct flCairoRegion* r = (struct flCairoRegion*)ip->region; cairo_region_t* r = (cairo_region_t*)ip->region;
if (!window->buffer || pWindow->as_overlay_window()) r = NULL; if (!window->buffer || pWindow->as_overlay_window()) r = NULL;
Fl_Wayland_Window_Driver::in_flush_ = true; Fl_Wayland_Window_Driver::in_flush_ = true;