Skip to content

Instantly share code, notes, and snippets.

@chipaca

chipaca/foo.c Secret

Created February 8, 2021 15:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chipaca/e86bc8affcb7d0cda2d2ae0fc8d30a62 to your computer and use it in GitHub Desktop.
Save chipaca/e86bc8affcb7d0cda2d2ae0fc8d30a62 to your computer and use it in GitHub Desktop.
grab font and use it in one go
/* 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