-
-
Save tagoh/447f847f3f651695482508bb40980a33 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
/* | |
* gcc -o mix mix.c `pkg-config --cflags --libs freetype2 x11 xrender` | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <X11/Xlib.h> | |
#include <X11/extensions/Xrender.h> | |
#include <ft2build.h> | |
#include FT_FREETYPE_H | |
FT_Library library; | |
GlyphSet | |
load_glyphset(Display *dpy, char *filename, int size, char *s, int *x) | |
{ | |
FT_Face face; | |
XRenderPictFormat *fmt = XRenderFindStandardFormat(dpy, PictStandardA8); | |
GlyphSet gs = XRenderCreateGlyphSet(dpy, fmt); | |
int i, idx; | |
if (FT_New_Face(library, filename, 0, &face) != FT_Err_Ok) { | |
printf("Unable to open %s\n", filename); | |
return 0; | |
} | |
if (FT_Set_Char_Size(face, 0, size /* pt */ << 6 /* 1/64 */, | |
96 /* dpi */, 96) != FT_Err_Ok) { | |
printf("Unable to set size for Noto Sans\n"); | |
gs = 0; | |
goto bail; | |
} | |
for (i = 0; s[i] != 0; i++) { | |
FT_Bitmap *bitmap; | |
XGlyphInfo ginfo; | |
Glyph gid; | |
int stride; | |
char *tmp; | |
int y; | |
idx = FT_Get_Char_Index(face, s[i]); | |
if (FT_Load_Glyph(face, idx, FT_LOAD_RENDER) != FT_Err_Ok) { | |
printf("Unable to load a glyph %02X\n", s[i]); | |
continue; | |
} | |
bitmap = &face->glyph->bitmap; | |
ginfo.x = -face->glyph->bitmap_left; | |
ginfo.y = face->glyph->bitmap_left; | |
ginfo.width = bitmap->width; | |
ginfo.height = bitmap->rows; | |
ginfo.xOff = face->glyph->advance.x >> 6; | |
ginfo.yOff = face->glyph->advance.y >> 6; | |
gid = s[i]; | |
stride = (ginfo.width + 3) & ~3; | |
tmp = malloc(stride * ginfo.height); | |
for (y = 0; y < ginfo.height; y++) | |
memcpy(tmp+y*stride, bitmap->buffer+y*ginfo.width, ginfo.width); | |
XRenderAddGlyphs(dpy, gs, &gid, &ginfo, 1, tmp, stride*ginfo.height); | |
XSync(dpy, 0); | |
*x += face->glyph->advance.x >> 6; | |
free(tmp); | |
} | |
bail: | |
FT_Done_Face(face); | |
return gs; | |
} | |
int | |
main(void) | |
{ | |
FT_Error fterr; | |
FT_Face facea, facen; | |
char a[] = "ABCD"; | |
char n[] = "0123"; | |
Display *dpy; | |
int screen, xa = 0, xn = 0; | |
Window root, w; | |
XRenderPictureAttributes pict_attr, pict_attr_pen; | |
XRenderPictFormat *fmt, *fmt_pen; | |
Picture pict, fg_pen; | |
XRenderColor color = { .red = 0, .green = 0, .blue = 0, .alpha = 0xffff}; | |
XRenderColor bg_color = { .red = 0xffff, .green = 0xffff, .blue = 0xffff, .alpha = 0xffff}; | |
Pixmap pixmap; | |
GlyphSet gsa, gsn; | |
dpy = XOpenDisplay(NULL); | |
screen = DefaultScreen(dpy); | |
root = DefaultRootWindow(dpy); | |
w = XCreateWindow(dpy, root, 0, 0, 640, 480, 0, | |
DefaultDepth(dpy, screen), InputOutput, | |
DefaultVisual(dpy, screen), 0, NULL); | |
pict_attr.poly_edge = PolyEdgeSmooth; | |
pict_attr.poly_mode = PolyModeImprecise; | |
fmt = XRenderFindStandardFormat(dpy, PictStandardRGB24); | |
pict = XRenderCreatePicture(dpy, w, fmt, CPPolyEdge|CPPolyMode, &pict_attr); | |
XSelectInput(dpy, w, KeyPressMask|KeyReleaseMask|ExposureMask|ButtonPressMask|StructureNotifyMask); | |
fmt_pen = XRenderFindStandardFormat(dpy, PictStandardARGB32); | |
pixmap = XCreatePixmap(dpy, root, 1, 1, 32); | |
pict_attr_pen.repeat = 1; | |
fg_pen = XRenderCreatePicture(dpy, pixmap, fmt_pen, CPRepeat, &pict_attr_pen); | |
XRenderFillRectangle(dpy, PictOpOver, fg_pen, &color, 0, 0, 1, 1); | |
XFreePixmap(dpy, pixmap); | |
fterr = FT_Init_FreeType(&library); | |
if (fterr) { | |
printf("Failed to initialize FreeType\n"); | |
return 1; | |
} | |
gsa = load_glyphset(dpy, "/usr/share/fonts/google-noto-vf/NotoSans[wght].ttf", 24, a, &xa); | |
gsn = load_glyphset(dpy, "/usr/share/fonts/google-noto-vf/NotoSansArabic[wght].ttf", 24, n, &xn); | |
XMapWindow(dpy, w); | |
while (1) { | |
XEvent event; | |
XNextEvent(dpy, &event); | |
switch (event.type) { | |
case Expose: | |
XRenderFillRectangle(dpy, PictOpOver, pict, &bg_color, 0, 0, 1640, 1640); | |
XRenderCompositeString8(dpy, PictOpOver, | |
fg_pen, pict, 0, gsa, | |
0, 0, 20, 50, a, 4); | |
XRenderCompositeString8(dpy, PictOpOver, | |
fg_pen, pict, 0, gsn, | |
0, 0, 20+xa, 50, n, 4); | |
break; | |
case DestroyNotify: | |
printf("Destroying\n"); | |
return 0; | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment