text.c.bak (4686B)
1 /* 2 * This file is part of the Lumidify ToolKit (LTK) 3 * Copyright (c) 2016, 2017 Lumidify Productions <lumidify@openmailbox.org> 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * of this software and associated documentation files (the "Software"), to deal 7 * in the Software without restriction, including without limitation the rights 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 * copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in all 13 * copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <stdint.h> 27 #include <X11/Xlib.h> 28 #include <X11/Xutil.h> 29 #include "text.h" 30 31 uint32_t u8_nextmemchar(const char *s, size_t *i) 32 { 33 uint32_t ch = 0; 34 size_t sz = 0; 35 do { 36 ch <<= 6; 37 ch += (unsigned char)s[(*i)++]; 38 sz++; 39 } while (!isutf(s[*i])); 40 ch -= offsetsFromUTF8[sz-1]; 41 42 return ch; 43 } 44 45 stbtt_fontinfo ltk_load_font(const char *path) 46 { 47 FILE *f; 48 long len; 49 char *contents; 50 stbtt_fontinfo info; 51 f = fopen(path, "rb"); 52 fseek(f, 0, SEEK_END); 53 len = ftell(f); 54 fseek(f, 0, SEEK_SET); 55 contents = malloc(len + 1); 56 fread(contents, 1, len, f); 57 contents[len] = '\0'; 58 fclose(f); 59 if (!stbtt_InitFont(&info, contents, 0)) 60 { 61 fprintf(stderr, "Failed to load font %s\n", path); 62 exit(1); 63 } 64 return info; 65 } 66 67 int ltk_text_width(uint8_t *text, stbtt_fontinfo fontinfo, int height) 68 { 69 float scale = stbtt_ScaleForPixelHeight(&fontinfo, height); 70 size_t i = 0; 71 int length = strlen(text); 72 if (length < 1) return 0; 73 int temp_x; 74 int kern_advance; 75 int width = 0; 76 uint32_t char1; 77 uint32_t char2; 78 char1 = u8_nextmemchar(text, &i); 79 while(i <= length) 80 { 81 stbtt_GetCodepointHMetrics(&fontinfo, char1, &temp_x, 0); 82 width += temp_x * scale; 83 84 char2 = u8_nextmemchar(text, &i); 85 if (!char2) break; 86 kern_advance = stbtt_GetCodepointKernAdvance(&fontinfo, char1, char2); 87 width += kern_advance * scale; 88 char1 = char2; 89 } 90 91 return width; 92 } 93 94 Pixmap ltk_render_text( 95 Display *display, 96 Window window, 97 GC gc, 98 uint8_t *text, 99 stbtt_fontinfo fontinfo, 100 int height, 101 unsigned long fg, 102 unsigned long bg) 103 { 104 XWindowAttributes attrs; 105 XGetWindowAttributes(display, window, &attrs); 106 int depth = attrs.depth; 107 108 int width = ltk_text_width(text, fontinfo, height); 109 unsigned char *bitmap = calloc(sizeof(char), width * height); 110 float scale = stbtt_ScaleForPixelHeight(&fontinfo, height); 111 112 int ascent, descent, line_gap; 113 stbtt_GetFontVMetrics(&fontinfo, &ascent, &descent, &line_gap); 114 ascent *= scale; 115 descent *= scale; 116 117 size_t i = 0; 118 int length = strlen(text); 119 if (length < 1) 120 { 121 printf("WARNING: ltk_render_text: length of text is less than 1.\n"); 122 return XCreatePixmap(display, window, 0, 0, depth); 123 } 124 uint32_t char1, char2; 125 char1 = u8_nextmemchar(text, &i); 126 int ax, x = 0, y, x1, y1, x2, y2, byte_offset, kern_advance; 127 while (i <= length) 128 { 129 stbtt_GetCodepointBitmapBox(&fontinfo, char1, scale, scale, &x1, &y1, &x2, &y2); 130 y = ascent + y1; 131 byte_offset = x + (y * width); 132 stbtt_MakeCodepointBitmap(&fontinfo, bitmap + byte_offset, x2 - x1, y2 - y1, width, scale, scale, char1); 133 134 stbtt_GetCodepointHMetrics(&fontinfo, char1, &ax, 0); 135 x += ax * scale; 136 137 char2 = u8_nextmemchar(text, &i); 138 if (!char2) break; 139 kern_advance = stbtt_GetCodepointKernAdvance(&fontinfo, char1, char2); 140 x += kern_advance * scale; 141 char1 = char2; 142 } 143 144 /* TODO: separate this into a separate function so that one function only creates 145 * the bitmap and other functions to turn that into a pixmap with solid color 146 * background, image background, etc. 147 */ 148 Pixmap rendered = XCreatePixmap(display, window, width, height, depth); 149 XSetForeground(display, gc, bg); 150 for (int i = 0; i < height; i++) 151 { 152 for (int j = 0; j < width; j++) 153 { 154 /* Yay! Magic! */ 155 XSetForeground(display, gc, (bitmap[i * width + j] / 255.0) * fg + ((255 - bitmap[i * width + j]) / 255.0) * bg); 156 XDrawPoint(display, rendered, gc, j, i); 157 } 158 } 159 XSetForeground(display, gc, bg); 160 return rendered; 161 }