-
-
Save chipaca/e86bc8affcb7d0cda2d2ae0fc8d30a62 to your computer and use it in GitHub Desktop.
grab font and use it in one go
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
/* gcc -o foo foo.c -D_GNU_SOURCE -std=c11 -pedantic -Wall $(pkg-config --cflags --libs freetype2 xft x11 libcurl) */ | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/stat.h> | |
#include <sys/types.h> | |
#include <curl/curl.h> | |
#include <X11/Xft/Xft.h> | |
static void die(const char *msg) { | |
fprintf(stderr, "%s", msg); | |
exit(1); | |
} | |
static void win() { | |
Display *dpy; | |
int scr; | |
Visual *visual; | |
Colormap cmap; | |
Window win; | |
XftFont *font; | |
const char *fontname = "Hanalei:size=11:antialias=true"; | |
XftDraw *draw; | |
XftColor color; | |
/* Initialization. */ | |
dpy = XOpenDisplay(NULL); | |
if (!dpy) { | |
die("cannot open X11 display\n"); | |
} | |
scr = DefaultScreen(dpy); | |
visual = DefaultVisual(dpy, scr); | |
cmap = DefaultColormap(dpy, scr); | |
/* Window. */ | |
win = XCreateSimpleWindow(dpy, RootWindow(dpy, scr), 100, 100, 200, 100, 1, BlackPixel(dpy, scr), WhitePixel(dpy, scr)); | |
XSelectInput(dpy, win, ExposureMask | KeyPressMask); | |
XMapWindow(dpy, win); | |
/* Xft. */ | |
font = XftFontOpenName(dpy, scr, fontname); | |
if (!font) { | |
die("cannot load font\n"); | |
} | |
if (!XftColorAllocName(dpy, visual, cmap, "#0000ee", &color)) { | |
die("cannot allocate xft color\n"); | |
} | |
draw = XftDrawCreate(dpy, win, visual, cmap); | |
while(1) { | |
XEvent ev; | |
XNextEvent(dpy, &ev); | |
if (ev.type == Expose) { | |
XftDrawStringUtf8(draw, &color, font, 50, 50, (const FcChar8 *)"Hello Xft!", 10); | |
} | |
else if (ev.type == KeyPress) { | |
break; | |
} | |
} | |
/* Cleanup. Not necessary, only for the sake of completeness. */ | |
XftColorFree(dpy, visual, cmap, &color); | |
XftDrawDestroy(draw); | |
XDestroyWindow(dpy, win); | |
XCloseDisplay(dpy); | |
} | |
static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) | |
{ | |
size_t written = fwrite(ptr, size, nmemb, (FILE *)stream); | |
return written; | |
} | |
static void grab(FILE* fontfile) { | |
CURL *curl_handle; | |
CURLcode res; | |
curl_handle = curl_easy_init(); | |
if (!curl_handle) { | |
die("cannot init curl"); | |
} | |
curl_easy_setopt(curl_handle, CURLOPT_URL, "https://r.chipaca.com/hanalei.ttf"); | |
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data); | |
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, fontfile); | |
/* Perform the request, res will get the return code */ | |
res = curl_easy_perform(curl_handle); | |
/* Check for errors */ | |
if(res != CURLE_OK) { | |
die(curl_easy_strerror(res)); | |
} | |
/* always cleanup */ | |
curl_easy_cleanup(curl_handle); | |
curl_global_cleanup(); | |
} | |
void ensurefontfile() { | |
/* | |
This should try, in order, $HOME/.font, and otherwise | |
${XDG_DATA_HOME:-$HOME/.local/share}/fonts/, and if neither | |
exist, create the latter. | |
*/ | |
/* getting $HOME instead of getent is me being lazy */ | |
const char *home = getenv("HOME"); | |
if (!home) { | |
die("cannot get $HOME"); | |
} | |
// XXX: check home exists? | |
char path[1024]; /* sue me */ | |
// XXX: check these return values | |
stpcpy(stpcpy(path, home), "/.fonts"); | |
int dfd = open(path, O_RDONLY|O_DIRECTORY); | |
if (dfd<0) { | |
// TODO: check for ${XDG_DATA_HOME:-$HOME/.local/share/fonts} | |
die("can't open ~/.fonts, and can't be arsed to look in XDG data dir"); | |
} | |
int fd = openat(dfd, "hanalei.ttf", O_WRONLY|O_CREAT|O_EXCL, 0664); | |
if (fd == -1) { | |
if (errno == EEXIST) { | |
return; | |
} | |
die("cannot open font file location for download"); | |
} | |
FILE *f = fdopen(fd, "wb"); | |
if (!f) { | |
die("cannot _really_open font file (what)"); | |
} | |
grab(f); | |
fclose(f); | |
close(dfd); | |
} | |
int main() { | |
ensurefontfile(); | |
win(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment