diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2023-11-20 17:13:09 +0100 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2023-12-04 12:34:44 +0100 |
| commit | 3e61ec7044942ebaeda948c64df762a0250f8954 (patch) | |
| tree | 642c08a6f7b120c2237f5e457074670d0ccf3e86 /src/drivers/Wayland | |
| parent | b9ac6bd728659a7780d7cde024f34607601e8a7f (diff) | |
New member function Fl_Image_Surface::mask(Fl_RGB_Image*)
Diffstat (limited to 'src/drivers/Wayland')
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H | 6 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx | 75 |
2 files changed, 80 insertions, 1 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H b/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H index 285222ced..ae32ac3df 100644 --- a/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H +++ b/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H @@ -25,6 +25,12 @@ class Fl_Wayland_Image_Surface_Driver : public Fl_Image_Surface_Driver { public: Fl_Wayland_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off); ~Fl_Wayland_Image_Surface_Driver(); + void mask(const Fl_RGB_Image *) FL_OVERRIDE; + struct shape_data_type { + double scale; + cairo_pattern_t *mask_pattern_; + cairo_t *bg_cr; + } *shape_data_; void set_current() FL_OVERRIDE; void translate(int x, int y) FL_OVERRIDE; void untranslate() FL_OVERRIDE; diff --git a/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx index 83419e5b2..f25fe025d 100644 --- a/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx @@ -22,6 +22,7 @@ Fl_Wayland_Image_Surface_Driver::Fl_Wayland_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) { + shape_data_ = NULL; float s = 1; int d = 1; if (!off) { @@ -51,6 +52,19 @@ Fl_Wayland_Image_Surface_Driver::Fl_Wayland_Image_Surface_Driver(int w, int h, Fl_Wayland_Image_Surface_Driver::~Fl_Wayland_Image_Surface_Driver() { + if (shape_data_) { + cairo_surface_t *surf; + cairo_pattern_get_surface(shape_data_->mask_pattern_, &surf); + unsigned char *bits = cairo_image_surface_get_data(surf); + cairo_pattern_destroy(shape_data_->mask_pattern_); + delete[] bits; + struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ = + Fl_Wayland_Graphics_Driver::offscreen_buffer((Fl_Offscreen)shape_data_->bg_cr); + delete[] off_->buffer; + free(off_); + cairo_destroy(shape_data_->bg_cr); + free(shape_data_); + } if (offscreen && !external_offscreen) { struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer = Fl_Wayland_Graphics_Driver::offscreen_buffer(offscreen); @@ -91,10 +105,38 @@ void Fl_Wayland_Image_Surface_Driver::untranslate() { Fl_RGB_Image* Fl_Wayland_Image_Surface_Driver::image() { + if (shape_data_ && shape_data_->mask_pattern_) { + // draw above the secondary offscreen the main offscreen masked by mask_pattern_ + cairo_t *c = ((Fl_Cairo_Graphics_Driver*)driver())->cr(); + cairo_pattern_t *paint_pattern = cairo_pattern_create_for_surface(cairo_get_target(c)); + cairo_set_source(shape_data_->bg_cr, paint_pattern); + cairo_mask(shape_data_->bg_cr, shape_data_->mask_pattern_); + cairo_pattern_destroy(paint_pattern); + // copy secondary offscreen to the main offscreen + cairo_pattern_t *pat = cairo_pattern_create_for_surface(cairo_get_target(shape_data_->bg_cr)); + cairo_scale(c, shape_data_->scale, shape_data_->scale); + cairo_set_source(c, pat), + cairo_paint(c); + cairo_pattern_destroy(pat); + // delete secondary offscreen + cairo_surface_t *surf; + cairo_pattern_get_surface(shape_data_->mask_pattern_, &surf); + unsigned char *bits = cairo_image_surface_get_data(surf); + cairo_pattern_destroy(shape_data_->mask_pattern_); + delete[] bits; + struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ = + Fl_Wayland_Graphics_Driver::offscreen_buffer((Fl_Offscreen)shape_data_->bg_cr); + delete[] off_->buffer; + free(off_); + cairo_destroy(shape_data_->bg_cr); + free(shape_data_); + shape_data_ = NULL; + } + // Convert depth-4 image in draw_buffer to a depth-3 image while exchanging R and B colors struct Fl_Wayland_Graphics_Driver::draw_buffer *off_buf = Fl_Wayland_Graphics_Driver::offscreen_buffer(offscreen); - int height = off_buf->data_size / off_buf->stride; + int height = int(off_buf->data_size / off_buf->stride); uchar *rgb = new uchar[off_buf->width * height * 3]; uchar *p = rgb; uchar *q; @@ -111,3 +153,34 @@ Fl_RGB_Image* Fl_Wayland_Image_Surface_Driver::image() { image->alloc_array = 1; return image; } + + +void Fl_Wayland_Image_Surface_Driver::mask(const Fl_RGB_Image *mask) { + bool using_copy = false; + shape_data_ = (struct shape_data_type*)calloc(1, sizeof(struct shape_data_type)); + int W, H; + struct Fl_Wayland_Graphics_Driver::draw_buffer *off_buf = + Fl_Wayland_Graphics_Driver::offscreen_buffer(offscreen); + W = off_buf->width; + H = (int)(off_buf->data_size / off_buf->stride); + if (W != mask->data_w() || H != mask->data_h()) { + Fl_RGB_Image *copy = (Fl_RGB_Image*)mask->copy(W, H); + mask = copy; + using_copy = true; + } + shape_data_->mask_pattern_ = Fl_Cairo_Graphics_Driver::calc_cairo_mask(mask); + //duplicate current offscreen content to new cairo_t* shape_data_->bg_cr + int width, height; + printable_rect(&width, &height); + struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ = + (struct Fl_Wayland_Graphics_Driver::draw_buffer*)calloc(1, + sizeof(struct Fl_Wayland_Graphics_Driver::draw_buffer)); + Fl_Wayland_Graphics_Driver::cairo_init(off_, W, H, + cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, W), + CAIRO_FORMAT_RGB24); + cairo_set_user_data(off_->cairo_, &Fl_Wayland_Graphics_Driver::key, off_, NULL); + shape_data_->bg_cr = off_->cairo_; + memcpy(off_->buffer, off_buf->buffer, off_buf->data_size); + shape_data_->scale = double(width) / W; + if (using_copy) delete mask; +} |
