URI: 
       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 }