FLTK logo

[master] 145c04e - Wayland platform: add cached image drawing.

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[master] 145c04e - Wayland platform: add cached image drawing. "ManoloFLTK" Dec 02, 2021  
 
commit 145c04e06d8ec537b500532f906866a327531720
Author:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
AuthorDate: Fri May 28 11:55:00 2021 +0200
Commit:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
CommitDate: Wed Sep 29 12:14:55 2021 +0200

    Wayland platform: add cached image drawing.

 FL/platform_types.h                                |   2 +-
 src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H   |  10 +
 src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx | 208 ++++++++++++++++++++-
 3 files changed, 211 insertions(+), 9 deletions(-)

diff --git FL/platform_types.h FL/platform_types.h
index 4987fe7..49708e8 100644
--- FL/platform_types.h
+++ FL/platform_types.h
@@ -122,7 +122,7 @@ typedef struct HGLRC__ *GLContext;
 
 #elif defined(__WAYLAND__)
 typedef struct buffer *Fl_Offscreen; /**< an offscreen drawing buffer */
-typedef void* Fl_Bitmask; /**< mask */
+typedef struct _cairo_pattern* Fl_Bitmask;
 typedef struct flWaylandRegion* Fl_Region;
 typedef int FL_SOCKET; /**< socket or file descriptor */
 typedef void *EGLContext;
diff --git src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H
index 2627600..2bf11f8 100644
--- src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H
+++ src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H
@@ -46,6 +46,7 @@ class Fl_Wayland_Graphics_Driver : public Fl_Cairo_Graphics_Driver {
 private:
   cairo_surface_t *cairo_surface_;
   PangoLayout *dummy_pango_layout_; // used to measure text width before showing a window
+  void draw_cached_pattern_(Fl_Image *img, cairo_pattern_t *pat, int X, int Y, int W, int H, int cx, int cy);
 public:
   Fl_Wayland_Graphics_Driver();
   ~Fl_Wayland_Graphics_Driver();
@@ -79,6 +80,15 @@ public:
   void begin_points();
   void end_points();
   void transformed_vertex(double x, double y);
+  void draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy);
+  void cache(Fl_RGB_Image *rgb);
+  void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
+  void draw_bitmap(Fl_Bitmap *bm,int XP, int YP, int WP, int HP, int cx, int cy);
+  void cache(Fl_Bitmap *img);
+  void delete_bitmask(Fl_Bitmask bm);
+  void cache(Fl_Pixmap *pxm);
+  void draw_pixmap(Fl_Pixmap *rgb,int XP, int YP, int WP, int HP, int cx, int cy);
+  void uncache_pixmap(fl_uintptr_t p);
   static void init_built_in_fonts();
   static struct buffer *create_shm_buffer(int width, int height, uint32_t format, struct wld_window *window);
   static void buffer_release(struct wld_window *window);
diff --git src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
index d06b55a..2c5f7f0 100644
--- src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
@@ -32,6 +32,14 @@
 
 extern unsigned fl_cmap[256]; // defined in fl_color.cxx
 
+
+//TODO: put that in the graphics driver classes
+void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
+  fl_color(r,g,b);
+  fl_rectf(x,y,w,h);
+}
+
+
 static int create_anonymous_file(off_t size)
 {
   int ret;
@@ -154,6 +162,13 @@ Fl_Wayland_Graphics_Driver::Fl_Wayland_Graphics_Driver () : Fl_Cairo_Graphics_Dr
 }
 
 
+Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
+{
+  fl_graphics_driver = new Fl_Wayland_Graphics_Driver();
+  return fl_graphics_driver;
+}
+
+
 Fl_Wayland_Graphics_Driver::~Fl_Wayland_Graphics_Driver() {
   if (pango_layout_) g_object_unref(pango_layout_);
 }
@@ -401,7 +416,6 @@ void Fl_Wayland_Graphics_Driver::draw(const char* str, int n, float x, float y)
   pango_layout_set_text(pango_layout_, str, n);
   pango_cairo_show_layout(cairo_, pango_layout_);
   cairo_restore(cairo_);
-  check_status();
 }
 
 
@@ -656,14 +670,192 @@ void Fl_Wayland_Graphics_Driver::transformed_vertex(double x, double y) {
 }
 
 
-Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
-{
-  fl_graphics_driver = new Fl_Wayland_Graphics_Driver();
-  return fl_graphics_driver;
+void Fl_Wayland_Graphics_Driver::draw_cached_pattern_(Fl_Image *img, cairo_pattern_t *pat, int X, int Y, int W, int H, int cx, int cy) {
+  cairo_save(cairo_);
+  cairo_rectangle(cairo_, X-0.5, Y-0.5, W+1, H+1);
+  cairo_clip(cairo_);
+  if (img->d() >= 1) cairo_set_source(cairo_, pat);
+  cairo_matrix_t matrix;
+  cairo_matrix_init_scale(&matrix, double(img->data_w())/(img->w()+1), double(img->data_h())/(img->h()+1));
+  cairo_matrix_translate(&matrix, -X+0.5+cx, -Y+0.5+cy);
+  cairo_pattern_set_matrix(pat, &matrix);
+  cairo_mask(cairo_, pat);
+  cairo_restore(cairo_);
 }
 
 
-void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
-  fl_color(r,g,b);
-  fl_rectf(x,y,w,h);
+void Fl_Wayland_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) {
+  int X, Y, W, H;
+  // Don't draw an empty image...
+  if (!rgb->d() || !rgb->array) {
+    Fl_Graphics_Driver::draw_empty(rgb, XP, YP);
+    return;
+  }
+  if (start_image(rgb, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
+    return;
+  }
+  cairo_pattern_t *pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(rgb);
+  if (!pat) {
+    cache(rgb);
+    pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(rgb);
+  }
+  draw_cached_pattern_(rgb, pat, X, Y, W, H, cx, cy);
+}
+
+
+void Fl_Wayland_Graphics_Driver::cache(Fl_RGB_Image *rgb) {
+  int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, rgb->data_w());
+  uchar *BGRA = new uchar[stride * rgb->data_h()];
+  memset(BGRA, 0, stride * rgb->data_h());
+  int lrgb = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d();
+  uchar A = 0xff, R,G,B, *q;
+  const uchar *r;
+  float f = 1;
+  if (rgb->d() >= 3) { // color images
+    for (int j = 0; j < rgb->data_h(); j++) {
+      r = rgb->array + j * lrgb;
+      q = BGRA + j * stride;
+      for (int i = 0; i < rgb->data_w(); i++) {
+        R = *r;
+        G = *(r+1);
+        B = *(r+2);
+        if (rgb->d() == 4) {
+          A = *(r+3);
+          f = float(A)/0xff;
+        }
+        *q =  B * f;
+        *(q+1) =  G * f;
+        *(q+2) =  R * f;
+        *(q+3) =  A;
+        r += rgb->d(); q += 4;
+      }
+    }
+  } else if (rgb->d() == 1 || rgb->d() == 2) { // B&W
+    for (int j = 0; j < rgb->data_h(); j++) {
+      r = rgb->array + j * lrgb;
+      q = BGRA + j * stride;
+      for (int i = 0; i < rgb->data_w(); i++) {
+        G = *r;
+        if (rgb->d() == 2) {
+          A = *(r+1);
+          f = float(A)/0xff;
+        }
+        *(q) =  G * f;
+        *(q+1) =  G * f;
+        *(q+2) =  G * f;
+        *(q+3) =  A;
+        r += rgb->d(); q += 4;
+      }
+    }
+  }
+  cairo_surface_t *surf = cairo_image_surface_create_for_data(BGRA, CAIRO_FORMAT_ARGB32, rgb->data_w(), rgb->data_h(), stride);
+  if (cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS) return;
+  cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
+  *Fl_Graphics_Driver::id(rgb) = (fl_uintptr_t)pat;
+}
+
+
+void Fl_Wayland_Graphics_Driver::uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) {
+  cairo_pattern_t *pat = (cairo_pattern_t*)id_;
+  if (pat) {
+    cairo_surface_t *surf;
+    cairo_pattern_get_surface(pat, &surf);
+    cairo_pattern_destroy(pat);
+    cairo_surface_destroy(surf);
+    id_ = 0;
+  }
+}
+
+
+void Fl_Wayland_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm,int XP, int YP, int WP, int HP, int cx, int cy) {
+  int X, Y, W, H;
+  if (!bm->array) {
+    draw_empty(bm, XP, YP);
+    return;
+  }
+  if (start_image(bm, XP,YP,WP,HP,cx,cy,X,Y,W,H)) return;
+  cairo_pattern_t *pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(bm);
+  if (!pat) {
+    cache(bm);
+    pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(bm);
+  }
+  if (pat) {
+    draw_cached_pattern_(bm, pat, X, Y, W, H, cx, cy);
+  }
+}
+
+
+void Fl_Wayland_Graphics_Driver::cache(Fl_Bitmap *bm) {
+  int stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, bm->data_w());
+  uchar *BGRA = new uchar[stride * bm->data_h()];
+  memset(BGRA, 0, stride * bm->data_h());
+    uchar  *r, p;
+    unsigned *q;
+    for (int j = 0; j < bm->data_h(); j++) {
+      r = (uchar*)bm->array + j * ((bm->data_w() + 7)/8);
+      q = (unsigned*)(BGRA + j * stride);
+      unsigned k = 0, mask32 = 1;
+      p = *r;
+      for (int i = 0; i < bm->data_w(); i++) {
+        if (p&1) (*q) |= mask32;
+        k++;
+        if (k % 8 != 0) p >>= 1; else p = *(++r);
+        if (k % 32 != 0) mask32 <<= 1; else {q++; mask32 = 1;}
+      }
+    }
+  cairo_surface_t *surf = cairo_image_surface_create_for_data(BGRA, CAIRO_FORMAT_A1, bm->data_w(), bm->data_h(), stride);
+  if (cairo_surface_status(surf) == CAIRO_STATUS_SUCCESS) {
+    cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
+    *Fl_Graphics_Driver::id(bm) = (fl_uintptr_t)pat;
+  }
+}
+
+
+void Fl_Wayland_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) {
+  cairo_pattern_t *pat = (cairo_pattern_t*)bm;
+  if (pat) {
+    cairo_surface_t *surf;
+    cairo_pattern_get_surface(pat, &surf);
+    cairo_pattern_destroy(pat);
+    cairo_surface_destroy(surf);
+  }
+}
+
+
+void Fl_Wayland_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) {
+  int X, Y, W, H;
+  // Don't draw an empty image...
+  if (!pxm->data() || !pxm->w()) {
+    Fl_Graphics_Driver::draw_empty(pxm, XP, YP);
+    return;
+  }
+  if (start_image(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
+    return;
+  }
+  cairo_pattern_t *pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(pxm);
+  if (!pat) {
+    cache(pxm);
+    pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(pxm);
+  }
+  draw_cached_pattern_(pxm, pat, X, Y, W, H, cx, cy);
+}
+
+
+void Fl_Wayland_Graphics_Driver::cache(Fl_Pixmap *pxm) {
+  Fl_RGB_Image *rgb = new Fl_RGB_Image(pxm);
+  cache(rgb);
+  *Fl_Graphics_Driver::id(pxm) = *Fl_Graphics_Driver::id(rgb);
+  *Fl_Graphics_Driver::id(rgb) = 0;
+  delete rgb;
+}
+
+
+void Fl_Wayland_Graphics_Driver::uncache_pixmap(fl_uintptr_t p) {
+  cairo_pattern_t *pat = (cairo_pattern_t*)p;
+  if (pat) {
+    cairo_surface_t *surf;
+    cairo_pattern_get_surface(pat, &surf);
+    cairo_pattern_destroy(pat);
+    cairo_surface_destroy(surf);
+  }
 }
Direct Link to Message ]
 
     
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.