En fouillant dans de vieux répertoires, j'ai trouvé un exemple utilisant CAIRO_FORMAT_A1
y cairo_mask_surface
qui pourrait être plus proche de ce que vous souhaitez que les autres exemples (et qui dément certaines de mes affirmations ci-dessus). Et celui-ci est complet. Compilez avec ce makefile
CFLAGS=-I/usr/include/cairo #-Wa,-alh
LDLIBS=-lcairo
en utilisant make mask
/* mask.c test program for cairo bit mask
makes a big blue turkey from the Postscript manual */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <cairo.h>
#include <X11/Xlib.h>
#include <cairo-xlib.h>
#include <unistd.h>
enum { little, big } endian = little;
unsigned char reversebits (unsigned char b) {
return (b & 0x01? 0x80: 0)
| (b & 0x02? 0x40: 0)
| (b & 0x04? 0x20: 0)
| (b & 0x08? 0x10: 0)
| (b & 0x10? 0x08: 0)
| (b & 0x20? 0x04: 0)
| (b & 0x40? 0x02: 0)
| (b & 0x80? 0x01: 0)
;
}
void paintmask(cairo_t *cr, unsigned char *samp, int w, int h) {
int span; /* width in bytes */
int stride; /* width in words */
cairo_surface_t *mask;
unsigned char *data;
int i,j,k;
uint32_t u;
stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, w);
/* stride = (w/32) + (w%32 ? 1 : 0) */
span = w/8 + (w%8? 1: 0);
printf("stride = %d\n", stride);
data = malloc(h * stride);
/* convert bytes to 32bit quantities matching
endianness of the machine */
/* each row */
for (i = 0; i < h; i++) {
/* each 32bit int in row */
for (j = 0; j < stride/4; j++) {
u = 0; /* zero the word */
/* each 8bit byte in 32bit int from samples */
for (k = 0; k < 4; k++) {
uint8_t b;
u <<= 8;
if (j*4+k < span) {
/* postscript input is always big-endian */
/* so grab most-significant byte */
b = samp[i*span + j*4 + k];
if (endian == little) {
//b = samp[i*span + j*4 + (4-1-k)];
b = reversebits(b);
}
u |= b;
}
//printf("%X\n", u);
} /* k */
printf("%08X\n", u);
*((uint32_t *)(data + i*stride + j)) = u;
} /* j */
} /* i */
mask = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_A1, w, h, stride);
cairo_mask_surface(cr, mask, 0, 0);
}
int main (int argc, char *argv[])
{
int width = 480;
int height = 460;
Display *dis;
int scr;
int depth;
Visual *vis;
XSetWindowAttributes attr;
unsigned long attrmask;
Window win;
cairo_surface_t *surface;
cairo_t *cr;
dis = XOpenDisplay(NULL);
scr = DefaultScreen(dis);
depth = DefaultDepth(dis, scr);
vis = DefaultVisual(dis, scr);
attr.background_pixel = WhitePixel(dis, scr);
attr.border_pixel = BlackPixel(dis, scr);
attr.event_mask = ExposureMask | StructureNotifyMask | ButtonPressMask;
attrmask = CWColormap | CWBackPixel | CWBorderPixel | CWEventMask;
win = XCreateWindow(dis, RootWindow(dis, scr),
200, 10, //pos
width, height, 5, //width height border
depth,
InputOutput,
vis,
attrmask, &attr);
XMapWindow(dis, win);
surface = cairo_xlib_surface_create(dis, win, vis, width, height);
cr = cairo_create(surface);
cairo_scale(cr, 10, 10);
cairo_set_source_rgb(cr, 0, 0, 1);
{
unsigned char samp[] = {
0x00, 0x3B, 0x00,
0x00, 0x27, 0x00,
0x00, 0x24, 0x80,
0x0E, 0x49, 0x40,
0x11, 0x49, 0x20,
0x14, 0xB2, 0x20,
0x3C, 0xB6, 0x50,
0x75, 0xFE, 0x88,
0x17, 0xFF, 0x8C,
0x17, 0x5F, 0x14,
0x1C, 0x07, 0xE2,
0x38, 0x03, 0xC4,
0x70, 0x31, 0x82,
0xF8, 0xED, 0xFC,
0xB2, 0xBB, 0xC2,
0xBB, 0x6F, 0x84,
0x31, 0xBF, 0xC2,
0x18, 0xEA, 0x3C,
0x0E, 0x3E, 0x00,
0x07, 0xFC, 0x00,
0x03, 0xF8, 0x00,
0x1E, 0x18, 0x00,
0x1F, 0xF8, 0x00 };
/*
*/
unsigned char samp2[] = {
0x00, 0x3B, 0x00, 0x00, 0x3B, 0x00,
0x00, 0x27, 0x00, 0x00, 0x27, 0x00,
0x00, 0x24, 0x80, 0x00, 0x24, 0x80,
0x0E, 0x49, 0x40, 0x0E, 0x49, 0x40,
0x11, 0x49, 0x20, 0x11, 0x49, 0x20,
0x14, 0xB2, 0x20, 0x14, 0xB2, 0x20,
0x3C, 0xB6, 0x50, 0x3C, 0xB6, 0x50,
0x75, 0xFE, 0x88, 0x75, 0xFE, 0x88,
0x17, 0xFF, 0x8C, 0x17, 0xFF, 0x8C,
0x17, 0x5F, 0x14, 0x17, 0x5F, 0x14,
0x1C, 0x07, 0xE2, 0x1C, 0x07, 0xE2,
0x38, 0x03, 0xC4, 0x38, 0x03, 0xC4,
0x70, 0x31, 0x82, 0x70, 0x31, 0x82,
0xF8, 0xED, 0xFC, 0xF8, 0xED, 0xFC,
0xB2, 0xBB, 0xC2, 0xB2, 0xBB, 0xC2,
0xBB, 0x6F, 0x84, 0xBB, 0x6F, 0x84,
0x31, 0xBF, 0xC2, 0x31, 0xBF, 0xC2,
0x18, 0xEA, 0x3C, 0x18, 0xEA, 0x3C,
0x0E, 0x3E, 0x00, 0x0E, 0x3E, 0x00,
0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00,
0x03, 0xF8, 0x00, 0x03, 0xF8, 0x00,
0x1E, 0x18, 0x00, 0x1E, 0x18, 0x00,
0x1F, 0xF8, 0x00, 0x1F, 0xF8, 0x00 };
//paintmask(cr, samp, 24, 23);
paintmask(cr, samp2, 48, 23);
XFlush(dis);
}
sleep(20);
cairo_destroy(cr);
cairo_surface_destroy(surface);
return 0;
}