text.c - ltkx - GUI toolkit for X11 (old)
HTML git clone git://lumidify.org/ltkx.git (fast, but not encrypted)
HTML git clone https://lumidify.org/ltkx.git (encrypted, but very slow)
HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltkx.git (over tor)
DIR Log
DIR Files
DIR Refs
DIR README
DIR 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 }