ltkx

GUI toolkit for X11 (old)
git clone git://lumidify.org/ltkx.git (fast, but not encrypted)
git clone https://lumidify.org/ltkx.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltkx.git (over tor)
Log | Files | Refs | README | LICENSE

text.c (7891B)


      1 #include <X11/Xlib.h>
      2 #include <X11/Xutil.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <stdint.h>
      6 #include "stb_truetype.h"
      7 #include <graphite2/Segment.h>
      8 
      9 /* These unicode routines are taken from
     10  * https://github.com/JeffBezanson/cutef8 */
     11 
     12 /* is c the start of a utf8 sequence? */
     13 #define isutf(c) (((c)&0xC0)!=0x80)
     14 
     15 static const uint32_t offsetsFromUTF8[6] = {
     16     0x00000000UL, 0x00003080UL, 0x000E2080UL,
     17     0x03C82080UL, 0xFA082080UL, 0x82082080UL
     18 };
     19 
     20 /* next character without NUL character terminator */
     21 uint32_t u8_nextmemchar(const char *s, size_t *i)
     22 {
     23     uint32_t ch = 0;
     24     size_t sz = 0;
     25     do {
     26         ch <<= 6;
     27         ch += (unsigned char)s[(*i)++];
     28         sz++;
     29     } while (!isutf(s[*i]));
     30     ch -= offsetsFromUTF8[sz-1];
     31 
     32     return ch;
     33 }
     34 
     35 
     36 #define STB_TRUETYPE_IMPLEMENTATION
     37 #include "stb_truetype.h" /* http://nothings.org/stb/stb_truetype.h */
     38 
     39 stbtt_fontinfo ltk_load_font(const char *path)
     40 {
     41 	FILE *f;
     42 	long len;
     43 	char *contents;
     44 	stbtt_fontinfo info;
     45 	f = fopen(path, "rb");
     46 	fseek(f, 0, SEEK_END);
     47 	len = ftell(f);
     48 	fseek(f, 0, SEEK_SET);
     49 	contents = malloc(len + 1);
     50 	fread(contents, 1, len, f);
     51 	contents[len] = '\0';
     52 	fclose(f);
     53 	if (!stbtt_InitFont(&info, contents, 0))
     54 	{
     55 		fprintf(stderr, "Failed to load font %s\n", path);
     56 		exit(1);
     57 	}
     58 	return info;
     59 }
     60 
     61 int ltk_text_width(uint8_t *text, stbtt_fontinfo fontinfo, int height)
     62 {
     63 	float scale = stbtt_ScaleForPixelHeight(&fontinfo, height);
     64 	size_t i = 0;
     65 	int length = strlen(text);
     66 	if (length < 1) return 0;
     67 	int temp_x;
     68 	int kern_advance;
     69 	int width = 0;
     70 	uint32_t char1;
     71 	uint32_t char2;
     72 	char1 = u8_nextmemchar(text, &i);
     73 	while(i <= length)
     74 	{
     75 		stbtt_GetCodepointHMetrics(&fontinfo, char1, &temp_x, 0);
     76 		width += temp_x * scale;
     77 
     78 		char2 = u8_nextmemchar(text, &i);
     79 		if (!char2) break;
     80 		kern_advance = stbtt_GetCodepointKernAdvance(&fontinfo, char1, char2);
     81 		width += kern_advance * scale;
     82 		char1 = char2;
     83 	}
     84 
     85 	return width;
     86 }
     87 
     88 Pixmap ltk_render_text(
     89 	Display *display,
     90 	Window window,
     91 	GC gc,
     92 	uint8_t *text,
     93 	stbtt_fontinfo fontinfo,
     94 	int height,
     95 	unsigned long fg,
     96 	unsigned long bg,
     97 	const char *font_
     98 )
     99 {
    100         int rtl = 1; /*are we rendering right to left? probably not */
    101         int pointsize = 24; /*point size in points */
    102         int dpi = 96; /*work with this many dots per inch */
    103         char *pError; /*location of faulty utf-8 */
    104         gr_font *font = NULL;
    105         size_t numCodePoints = 0;
    106         gr_segment *seg = NULL;
    107         const gr_slot *s;
    108         gr_face *face = gr_make_file_face(font_, 0);
    109         if (!face) return 1;
    110         //font = gr_make_font(pointsize * dpi / 72.0f, face);
    111         font = gr_make_font(pointsize * dpi / 72.0f, face);
    112         if (!font) return 2;
    113         numCodePoints = gr_count_unicode_characters(gr_utf8, text, NULL, (const void **)(&pError));
    114         if (pError) return 3;
    115         seg = gr_make_seg(font, face, 0, 0, gr_utf8, text, numCodePoints, rtl);
    116         if (!seg) return 3;
    117         for (s = gr_seg_first_slot(seg); s; s = gr_slot_next_in_segment(s))
    118                 printf("%d(%f,%f) ", gr_slot_gid(s), gr_slot_origin_X(s), gr_slot_origin_Y(s));
    119 	//printf("\n%f\n", gr_seg_advance_X(seg));
    120 
    121 	XWindowAttributes attrs;
    122 	XGetWindowAttributes(display, window, &attrs);
    123 	int depth = attrs.depth;
    124 
    125 //	int width = ltk_text_width(text, fontinfo, height);
    126 	int width = (int)gr_seg_advance_X(seg) + 100;
    127 	unsigned char *bitmap = calloc(sizeof(char), width * (height + 200));
    128 	//float scale = stbtt_ScaleForPixelHeight(&fontinfo, pointsize * dpi / 72.0f);
    129 	float scale = stbtt_ScaleForMappingEmToPixels(&fontinfo, pointsize * dpi / 72.0f);
    130 
    131 	int ascent, descent, line_gap;
    132 	stbtt_GetFontVMetrics(&fontinfo, &ascent, &descent, &line_gap);
    133 	ascent *= scale;
    134 	descent *= scale;
    135 
    136 	size_t i = 0;
    137 	int length = strlen(text);
    138 	if (length < 1)
    139 	{
    140 		printf("WARNING: ltk_render_text: length of text is less than 1.\n");
    141 		return XCreatePixmap(display, window, 0, 0, depth);
    142 	}
    143 	uint32_t char1, char2;
    144 	char1 = u8_nextmemchar(text, &i);
    145 	int ax, lsb, x = 0, y = 0, x1, y1, x2, y2, byte_offset, kern_advance;
    146 	int w, h, xoff, yoff;
    147 	int y_abs = 0;
    148 //	while (i <= length)
    149 	unsigned char *b;
    150         for (s = gr_seg_first_slot(seg); s; s = gr_slot_next_in_segment(s))
    151 	{
    152 		stbtt_GetGlyphBitmapBox(&fontinfo, gr_slot_gid(s), scale, scale, &x1, &y1, &x2, &y2);
    153 		//stbtt_MakeGlyphBitmap(&fontinfo, bitmap + byte_offset, x2 - x1, y2 - y1, width, scale, scale, gr_slot_gid(s));
    154                 b = stbtt_GetGlyphBitmap(&fontinfo, scale, scale, gr_slot_gid(s), &w, &h, &xoff, &yoff);
    155 		x = (int)(50 + xoff + gr_slot_origin_X(s));
    156 		y = (int)(200 + yoff - gr_slot_origin_Y(s));
    157                 for (int i = 0; i < h; i++)
    158                 {
    159                         for (int j = 0; j < w; j++)
    160                         {
    161 				byte_offset = (y + i) * width + x + j;
    162                                 bitmap[byte_offset] = bitmap[byte_offset] + b[i * w + j];
    163                                 if (bitmap[byte_offset] > 255) bitmap[byte_offset] = 255;
    164                         }
    165                 }
    166                 free(b);
    167 	}
    168         gr_seg_destroy(seg);
    169         gr_font_destroy(font);
    170         gr_face_destroy(face);
    171 
    172 	/* TODO: separate this into a separate function so that one function only creates
    173 	 * the bitmap and other functions to turn that into a pixmap with solid color
    174 	 * background, image background, etc.
    175 	 */
    176 	Pixmap rendered = XCreatePixmap(display, window, width, height + 200, depth);
    177 	XSetForeground(display, gc, bg);
    178 	for (int i = 0; i < (height + 200); i++)
    179 	{
    180 		for (int j = 0; j < width; j++)
    181 		{
    182 			/* Yay! Magic! */
    183 			XSetForeground(display, gc, (bitmap[i * width + j] / 255.0) * fg + (1 - bitmap[i * width + j] / 255.0) * bg);
    184 			XDrawPoint(display, rendered, gc, j, i);
    185 		}
    186 	}
    187 	XSetForeground(display, gc, bg);
    188 	return rendered;
    189 }
    190 
    191 int main(int argc, char *argv[])
    192 {
    193     Display *display;
    194     int screen;
    195     Window window;
    196     GC gc;
    197 
    198     unsigned long black, white;
    199     Colormap colormap;
    200     display = XOpenDisplay((char *)0);
    201     screen = DefaultScreen(display);
    202     colormap = DefaultColormap(display, screen);
    203     black = BlackPixel(display, screen);
    204     white = WhitePixel(display, screen);
    205     window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, 1366, 512, 0, black, white);
    206     XSetStandardProperties(display, window, "Random Window", NULL, None, NULL, 0, NULL);
    207     XSelectInput(display, window, ExposureMask|ButtonPressMask|KeyPressMask);
    208     gc = XCreateGC(display, window, 0, 0);
    209     XSetBackground(display, gc, black);
    210     XSetForeground(display, gc, black);
    211     XClearWindow(display, window);
    212     XMapRaised(display, window);
    213     XColor c1, c2;
    214     XParseColor(display, colormap, "#FFFFFF", &c1);
    215     XParseColor(display, colormap, "#FF0000", &c2);
    216     XAllocColor(display, colormap, &c1);
    217     XAllocColor(display, colormap, &c2);
    218 
    219     stbtt_fontinfo fontinfo = ltk_load_font("Awami_beta3.ttf");
    220     int width = ltk_text_width("ہمارے بارے میںffsafdsfasfasf", fontinfo, 100);
    221     Pixmap pix = ltk_render_text(display, window, gc, "ہمارے بارے میں", fontinfo, 64, c1.pixel, c2.pixel, "Awami_beta3.ttf");
    222 //    Pixmap pix = ltk_render_text(display, window, gc, "Bob", fontinfo, 64, c1.pixel, c2.pixel, "GentiumPlus-R.ttf");
    223     XCopyArea(display, pix, window, gc, 0, 0, width, 64, 0, 0);
    224 
    225     XEvent event;
    226     KeySym key;
    227     char text[255];
    228 
    229     while(1)
    230     {
    231         XNextEvent(display, &event);
    232         if (event.type == KeyPress && XLookupString(&event.xkey, text, 255, &key, 0) == 1)
    233         {
    234             XCopyArea(display, pix, window, gc, 0, 0, width, 300, 0, 0);
    235             if (text[0] == 'q')
    236             {
    237                 XFreeGC(display, gc);
    238                 XFreeColormap(display, colormap);
    239                 XDestroyWindow(display, window);
    240                 XCloseDisplay(display);
    241                 exit(0);
    242             }
    243         }
    244     }
    245     
    246     return 0;
    247 }