Ver Fonte

stb_image with bit transparency

X11 do not support transparent images itself. So the clip mask is calculating in this code. X11 ClipMask support only bit transparency.
Dmitry Hrabrov há 8 anos atrás
pai
commit
5fc8a250aa
1 ficheiros alterados com 134 adições e 3 exclusões
  1. 134 3
      demo/x11/nuklear_xlib.h

+ 134 - 3
demo/x11/nuklear_xlib.h

@@ -1,5 +1,5 @@
 /*
- * Nuklear - v1.32.0 - public domain
+ * Nuklear - v1.40.8 - public domain
  * no warrenty implied; use at your own risk.
  * authored from 2015-2017 by Micha Mettke
  */
@@ -25,6 +25,10 @@ NK_API void                 nk_xlib_push_font(XFont*);
 NK_API void                 nk_xlib_paste(nk_handle, struct nk_text_edit*);
 NK_API void                 nk_xlib_copy(nk_handle, const char*, int len);
 
+/* Image */
+NK_API struct nk_image nk_xsurf_load_image_from_file(char const *filename);
+NK_API struct nk_image nk_xsurf_load_image_from_memory(const void *membuf, nk_uint membufSize);
+
 /* Font */
 NK_API XFont*               nk_xfont_create(Display *dpy, const char *name);
 NK_API void                 nk_xfont_del(Display *dpy, XFont *font);
@@ -48,6 +52,10 @@ NK_API void                 nk_xfont_del(Display *dpy, XFont *font);
 #include <unistd.h>
 #include <time.h>
 
+#define STB_IMAGE_IMPLEMENTATION
+#include "../stb_image.h"
+
+
 #ifndef NK_X11_DOUBLE_CLICK_LO
 #define NK_X11_DOUBLE_CLICK_LO 20
 #endif
@@ -56,6 +64,7 @@ NK_API void                 nk_xfont_del(Display *dpy, XFont *font);
 #endif
 
 typedef struct XSurface XSurface;
+typedef struct XImageWithAlpha XImageWithAlpha;
 struct XFont {
     int ascent;
     int descent;
@@ -72,6 +81,11 @@ struct XSurface {
     Drawable drawable;
     unsigned int w, h;
 };
+struct XImageWithAlpha {
+    XImage* ximage;
+    GC clipMaskGC;
+    Pixmap clipMask;
+};
 static struct  {
     char *clipboard_data;
     int clipboard_len;
@@ -260,7 +274,6 @@ NK_INTERN void
 nk_xsurf_stroke_triangle(XSurface *surf, short x0, short y0, short x1,
     short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
 {
-    XPoint pnts[3];
     unsigned long c = nk_color_from_byte(&col.r);
     XSetForeground(surf->dpy, surf->gc, c);
     XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
@@ -383,6 +396,121 @@ nk_xsurf_draw_text(XSurface *surf, short x, short y, unsigned short w, unsigned
     else XDrawString(surf->dpy, surf->drawable, surf->gc, tx, ty, (const char*)text, (int)len);
 }
 
+
+NK_INTERN struct nk_image
+nk_stbi_image_to_xsurf(unsigned char *data, int width, int height, int channels) {
+    XSurface *surf = xlib.surf;
+    struct nk_image img;
+    int bpl = channels;
+    long i, isize = width*height*channels;
+    XImageWithAlpha *aimage = (XImageWithAlpha*)calloc( 1, sizeof(XImageWithAlpha) );
+    int depth = DefaultDepth(surf->dpy, surf->screen); 
+    if (data == NULL) return nk_image_id(0);
+    if (aimage == NULL) return nk_image_id(0);
+    
+    switch (depth){
+        case 24:
+            bpl = 4;
+        break;
+        case 16:
+        case 15:
+            bpl = 2;
+        break;
+        default:
+            bpl = 1;
+        break;
+    }
+    
+    /* rgba to bgra */
+    if (channels >= 3){
+        for (i=0; i < isize; i += channels) {
+            unsigned char red  = data[i+2];
+            unsigned char blue = data[i];
+            data[i]   = red;
+            data[i+2] = blue;
+        }
+    }
+
+    if (channels == 4){
+        const unsigned alpha_treshold = 127;        
+        aimage->clipMask = XCreatePixmap(surf->dpy, surf->drawable, width, height, 1);
+        
+        if( aimage->clipMask ){
+            aimage->clipMaskGC = XCreateGC(surf->dpy, aimage->clipMask, 0, 0);
+            XSetForeground(surf->dpy, aimage->clipMaskGC, BlackPixel(surf->dpy, surf->screen));
+            XFillRectangle(surf->dpy, aimage->clipMask, aimage->clipMaskGC, 0, 0, width, height);
+
+            XSetForeground(surf->dpy, aimage->clipMaskGC, WhitePixel(surf->dpy, surf->screen));
+            for (i=0; i < isize; i += channels){
+                unsigned char alpha = data[i+3];
+                int div = i / channels;
+                int x = div % width;
+                int y = div / width;
+                if( alpha > alpha_treshold )
+                    XDrawPoint(surf->dpy, aimage->clipMask, aimage->clipMaskGC, x, y);
+            }
+        }
+    }
+    
+    aimage->ximage = XCreateImage(surf->dpy, 
+           CopyFromParent, depth, 
+           ZPixmap, 0, 
+           (char*)data, 
+           width, height, 
+           bpl*8, bpl * width); 
+    img = nk_image_ptr( (void*)aimage);
+    img.h = height;
+    img.w = width;
+    return img;
+}
+
+NK_API struct nk_image
+nk_xsurf_load_image_from_memory(const void *membuf, nk_uint membufSize)
+{
+    int x,y,n;
+    unsigned char *data;
+    data = stbi_load_from_memory(membuf, membufSize, &x, &y, &n, 0);
+    return nk_stbi_image_to_xsurf(data, x, y, n);
+}
+
+NK_API struct nk_image
+nk_xsurf_load_image_from_file(char const *filename)
+{
+    int x,y,n;
+    unsigned char *data;
+    data = stbi_load(filename, &x, &y, &n, 0);
+    return nk_stbi_image_to_xsurf(data, x, y, n);
+}
+
+NK_INTERN void
+nk_xsurf_draw_image(XSurface *surf, short x, short y, unsigned short w, unsigned short h,
+    struct nk_image img, struct nk_color col)
+{
+    XImageWithAlpha *aimage = img.handle.ptr;
+    if (aimage){
+        if (aimage->clipMask){
+            XSetClipMask(surf->dpy, surf->gc, aimage->clipMask);
+            XSetClipOrigin(surf->dpy, surf->gc, x, y); 
+        }
+        XPutImage(surf->dpy, surf->drawable, surf->gc, aimage->ximage, 0, 0, x, y, w, h);
+        XSetClipMask(surf->dpy, surf->gc, None);
+    }
+}
+
+void
+nk_xsurf_image_free(struct nk_image* image)
+{
+    XSurface *surf = xlib.surf;
+    XImageWithAlpha *aimage = image->handle.ptr;
+    if (!aimage) return;
+    /*stbi_image_free(aimage->ximage->data);*/
+    XDestroyImage(aimage->ximage);
+    XFreePixmap(surf->dpy, aimage->clipMask);
+    XFreeGC(surf->dpy, aimage->clipMaskGC);
+    free(aimage);
+}
+
+
 NK_INTERN void
 nk_xsurf_clear(XSurface *surf, unsigned long color)
 {
@@ -802,8 +930,11 @@ nk_xlib_render(Drawable screen, struct nk_color clear)
             nk_xsurf_stroke_curve(surf, q->begin, q->ctrl[0], q->ctrl[1],
                 q->end, 22, q->line_thickness, q->color);
         } break;
+        case NK_COMMAND_IMAGE: {
+            const struct nk_command_image *i = (const struct nk_command_image *)cmd;
+            nk_xsurf_draw_image(surf, i->x, i->y, i->w, i->h, i->img, i->col);
+        } break;
         case NK_COMMAND_RECT_MULTI_COLOR:
-        case NK_COMMAND_IMAGE:
         case NK_COMMAND_ARC:
         case NK_COMMAND_ARC_FILLED:
         case NK_COMMAND_CUSTOM: