text.c (3828B)
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 "text.h" 28 29 uint32_t u8_nextmemchar(const char *s, size_t *i) 30 { 31 uint32_t ch = 0; 32 size_t sz = 0; 33 do { 34 ch <<= 6; 35 ch += (unsigned char)s[(*i)++]; 36 sz++; 37 } while (!isutf(s[*i])); 38 ch -= offsetsFromUTF8[sz-1]; 39 40 return ch; 41 } 42 43 stbtt_fontinfo ltk_load_font(const char *path) 44 { 45 FILE *f; 46 long len; 47 char *contents; 48 stbtt_fontinfo info; 49 f = fopen(path, "rb"); 50 fseek(f, 0, SEEK_END); 51 len = ftell(f); 52 fseek(f, 0, SEEK_SET); 53 contents = malloc(len + 1); 54 fread(contents, 1, len, f); 55 contents[len] = '\0'; 56 fclose(f); 57 if (!stbtt_InitFont(&info, contents, 0)) 58 { 59 fprintf(stderr, "Failed to load font %s\n", path); 60 exit(1); 61 } 62 return info; 63 } 64 65 int ltk_text_width(uint8_t *text, stbtt_fontinfo fontinfo, int height) 66 { 67 float scale = stbtt_ScaleForPixelHeight(&fontinfo, height); 68 size_t i = 0; 69 int length = strlen(text); 70 if (length < 1) return 0; 71 int temp_x; 72 int kern_advance; 73 int width = 0; 74 uint32_t char1; 75 uint32_t char2; 76 char1 = u8_nextmemchar(text, &i); 77 while(i <= length) 78 { 79 stbtt_GetCodepointHMetrics(&fontinfo, char1, &temp_x, 0); 80 width += temp_x * scale; 81 82 char2 = u8_nextmemchar(text, &i); 83 if (!char2) break; 84 kern_advance = stbtt_GetCodepointKernAdvance(&fontinfo, char1, char2); 85 width += kern_advance * scale; 86 char1 = char2; 87 } 88 89 return width; 90 } 91 92 unsigned char *ltk_render_text(uint8_t *text, stbtt_fontinfo fontinfo, int height, int width) 93 { 94 /* int width = ltk_text_width(text, fontinfo, height);*/ 95 unsigned char *bitmap = calloc(width * height, sizeof(char)); 96 float scale = stbtt_ScaleForPixelHeight(&fontinfo, height); 97 98 int ascent, descent, line_gap; 99 stbtt_GetFontVMetrics(&fontinfo, &ascent, &descent, &line_gap); 100 ascent *= scale; 101 descent *= scale; 102 103 size_t i = 0; 104 int length = strlen(text); 105 if (length < 1) 106 { 107 printf("WARNING: ltk_render_text: length of text is less than 1.\n"); 108 return bitmap; 109 } 110 uint32_t char1, char2; 111 char1 = u8_nextmemchar(text, &i); 112 int ax, x = 0, y, x1, y1, x2, y2, byte_offset, kern_advance; 113 while (i <= length) 114 { 115 stbtt_GetCodepointBitmapBox(&fontinfo, char1, scale, scale, &x1, &y1, &x2, &y2); 116 y = ascent + y1; 117 byte_offset = x + (y * width); 118 stbtt_MakeCodepointBitmap(&fontinfo, bitmap + byte_offset, x2 - x1, y2 - y1, width, scale, scale, char1); 119 120 stbtt_GetCodepointHMetrics(&fontinfo, char1, &ax, 0); 121 x += ax * scale; 122 123 char2 = u8_nextmemchar(text, &i); 124 if (!char2) break; 125 kern_advance = stbtt_GetCodepointKernAdvance(&fontinfo, char1, char2); 126 x += kern_advance * scale; 127 char1 = char2; 128 } 129 130 return bitmap; 131 }