Created
May 12, 2020 09:56
-
-
Save nick87720z/53a1c952d479b67a7f2b096a88deed81 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
======= Makefile ======= | |
CFLAGS = -Wall -Wextra -O0 -g3 -ggdb3 `pkg-config --cflags x11 cairo pangocairo` | |
LDFLAGS = -O0 `pkg-config --libs x11 cairo pangocairo` | |
all: ui-cairo-x11 | |
ui-cairo-x11: ui-cairo-x11.o | |
ui-cairo-x11.o: ui-cairo-x11.c | |
clean: | |
rm *.o | |
run: | |
valgrind -s --leak-check=full --show-leak-kinds=all ./ui-cairo-x11 | |
.PHONY: clean run | |
======== ui-cairo-x11.c ======== | |
/* pkg-config: cairo, x11, xext, xrandr, pangocairo */ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <unistd.h> | |
#include <math.h> | |
#include <time.h> | |
#include <X11/Xlib.h> | |
#include <X11/Xutil.h> | |
#include <cairo-xlib.h> | |
#include <pango/pangocairo.h> | |
/* In-place counter wrapper code */ | |
#define begin_perf(time, idle_time, name) { \ | |
clock_t tstart = clock (); \ | |
clock_t tcur = 0; \ | |
guint64 counter = 0; \ | |
int sec = -(idle_time); \ | |
while (1) \ | |
{ \ | |
counter++; \ | |
tcur = clock (); \ | |
if (time == -1) \ | |
{ \ | |
printf ("clock doesn't work\n"); \ | |
break; \ | |
} \ | |
if ( tcur - tstart >= CLOCKS_PER_SEC ) \ | |
{ \ | |
sec++; \ | |
tstart = tcur; \ | |
if (sec <= 0) \ | |
{ \ | |
counter = 0; \ | |
continue; \ | |
} \ | |
printf ("%s: %lu cycles\n", (name), counter / sec); \ | |
if (sec >= (time)) \ | |
break; \ | |
} | |
#define end_perf \ | |
} \ | |
} | |
/*******************************/ | |
/* noop, unused */ | |
static void mainloop (void) | |
{ | |
while (1) | |
{ | |
break; | |
} | |
} | |
/* FIXME: helper to circumvent cairo bug, when subpixel rendering failed with some cairo clip paths */ | |
static void draw_pango_layout (cairo_t * cr, PangoLayout * layout, int x, int y) | |
{ | |
static cairo_surface_t * txt_surf = NULL; | |
static cairo_t * txt_cr = NULL; | |
cairo_pattern_t * cr_pat; | |
if (0) | |
cairo_save (cr); | |
else { | |
cr_pat = cairo_get_source (cr); | |
cairo_pattern_reference (cr_pat); | |
} | |
/* 2. surf creation */ | |
if (txt_surf == NULL || 1) | |
{ | |
txt_surf = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL); | |
txt_cr = cairo_create (txt_surf); | |
} | |
if (0) { | |
cairo_set_operator (txt_cr, CAIRO_OPERATOR_CLEAR); | |
cairo_paint (txt_cr); | |
cairo_set_operator (txt_cr, CAIRO_OPERATOR_OVER); | |
} | |
cairo_set_source (txt_cr, cairo_get_source (cr)); | |
pango_cairo_show_layout (txt_cr, layout); | |
cairo_set_source_surface (cr, txt_surf, x, y); | |
cairo_paint (cr); | |
/* -2. surf deconstruction */ | |
cairo_destroy (txt_cr); | |
cairo_surface_destroy (txt_surf); | |
if (0) | |
cairo_restore (cr); | |
else { | |
cairo_set_source (cr, cr_pat); | |
} | |
} | |
//#define TEXT "subpixel test" | |
#define TEXT "subpixel test subpixel test subpixel test subpixel test subpixel test subpixel test subpixel test subpixel test" | |
static void draw (cairo_t * cr) | |
{ | |
if (0) { /* Clear surface */ | |
cairo_operator_t op = cairo_get_operator (cr); | |
cairo_antialias_t aa = cairo_get_antialias (cr); | |
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); | |
cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); | |
cairo_set_source_rgba (cr, 0.4, 0.0, 0.7, 0.3); | |
cairo_paint (cr); | |
cairo_set_operator (cr, op); | |
cairo_set_antialias (cr, aa); | |
} | |
if (0) { /* test curve speedup (default value is 0.1) */ | |
cairo_set_tolerance (cr, 0.2); | |
} | |
if (0) { /* 360 deg circle path*/ | |
cairo_new_path (cr); | |
cairo_arc (cr, 110.5, 112.5, 100, 0, M_PI*2); | |
cairo_close_path (cr); | |
} | |
if (0) { /* rounded rectangle path */ | |
cairo_new_path (cr); | |
cairo_arc (cr, 100, 100, 40.5, -M_PI, -M_PI_2); | |
cairo_arc (cr, 200, 100, 40.5, -M_PI_2, 0); | |
cairo_arc (cr, 200, 200, 40.5, 0, M_PI_2); | |
cairo_arc (cr, 100, 200, 40.5, M_PI_2, M_PI); | |
cairo_close_path (cr); | |
} | |
if (0) { /* under-line (shadow) */ | |
cairo_set_line_width (cr, 3.0); | |
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.4); | |
cairo_stroke_preserve (cr); | |
} | |
if (0) { /* main line */ | |
cairo_set_line_width (cr, 1.0); | |
cairo_set_source_rgba (cr, 1.0, 0.8, 0.4, 1.0); | |
cairo_stroke (cr); | |
} | |
/* Issue test: text loses subpixel rendering in certain clip variants */ | |
if (0) { | |
cairo_new_path (cr); | |
cairo_move_to (cr, 0, 0); | |
cairo_line_to (cr, 110, 0); | |
cairo_line_to (cr, 400, 400); | |
cairo_line_to (cr, 0, 400); | |
cairo_close_path (cr); | |
cairo_clip_preserve (cr); | |
cairo_set_source_rgba (cr, 0, 0, 0, 0.4); | |
cairo_paint (cr); | |
} | |
/* text subpixel + clip workaround test */ | |
PangoFontDescription * font_desc; | |
font_desc = pango_font_description_from_string ("Mono 10"); | |
cairo_set_source_rgba (cr, 1, 1, 0.7, 1); | |
cairo_move_to (cr, 112, 110); | |
if (1) /* pango way */ | |
{ | |
PangoLayout * playout; | |
playout = pango_cairo_create_layout (cr); | |
pango_layout_set_text (playout, TEXT, -1); | |
pango_layout_set_font_description (playout, font_desc); | |
if (1) draw_pango_layout (cr, playout, 112, 110); | |
else pango_cairo_show_layout (cr, playout); | |
} | |
else /* cairo toy api way */ | |
{ | |
PangoContext * pcontext; | |
PangoCairoFont * pfont; | |
cairo_scaled_font_t * cfont; | |
cairo_text_extents_t ext; | |
pcontext = pango_cairo_create_context (cr); | |
pfont = PANGO_CAIRO_FONT (pango_context_load_font (pcontext, font_desc)); | |
cfont = pango_cairo_font_get_scaled_font (pfont); | |
cairo_set_scaled_font (cr, cfont); | |
cairo_text_extents (cr, TEXT, & ext); | |
//printf ("cairo text extents: %.0f×%.0f\n", ext.width, ext.height); | |
cairo_show_text (cr, TEXT); | |
} | |
} | |
int main (int argc, char ** argv) | |
{ | |
Display * display; | |
int screen, depth; | |
Window win, root; | |
XVisualInfo vinfo; | |
XSetWindowAttributes attr; | |
cairo_surface_t * surf; | |
cairo_t * cr; | |
const int | |
w=640, h=480, | |
bw=0; | |
display = XOpenDisplay (NULL); | |
screen = DefaultScreen (display); | |
depth = DefaultDepth(display,screen); | |
root = DefaultRootWindow (display); | |
printf ("Default depth: %i\n", depth); | |
fflush (stdout); | |
XMatchVisualInfo (display, screen, 32, TrueColor, &vinfo); | |
attr.colormap = XCreateColormap (display, root, vinfo.visual, AllocNone); | |
attr.border_pixel = 0; | |
attr.background_pixel = 0; | |
attr.background_pixmap = None; | |
win = XCreateWindow ( | |
display, root, | |
0, 0, w, h, | |
bw, vinfo.depth, InputOutput, vinfo.visual, | |
CWColormap | CWBorderPixel | CWBackPixmap | CWBackPixel, &attr); | |
//XMapWindow (display, win); | |
surf = cairo_xlib_surface_create ( | |
display, win, vinfo.visual, | |
w, h); | |
cr = cairo_create (surf); | |
begin_perf (60, 2, "draw()"); | |
draw (cr); | |
end_perf; | |
cairo_surface_flush (surf); | |
XSync (display, False); | |
sleep (6); | |
cairo_destroy (cr); | |
cairo_surface_destroy (surf); | |
XUnmapWindow (display, win); | |
XDestroyWindow (display, win); | |
XCloseDisplay (display); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment