ltkx

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltkx.git
Log | Files | Refs | README | LICENSE

commit ba0e522da0cb698021de15f24971b8c661d3941f
parent 7b5498e387d5d8d05ffaf404e665a32f2de32e75
Author: lumidify <nobody@lumidify.org>
Date:   Thu, 21 May 2020 18:01:08 +0200

Move unused files to unused/

Diffstat:
MMakefile | 2+-
Mbutton.c | 2+-
Mltk.c | 5+++--
Mltkx.h | 2+-
Dtemp | 1-
Mtest1.c | 2+-
Dtext-common.c | 410-------------------------------------------------------------------------------
Mtext_buffer.c | 2+-
Mtext_buffer.h | 2+-
Atext_common.c | 410+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rtext-common.h -> text_common.h | 0
Mtext_edit.c | 2+-
Dtmpfb.txt | 67-------------------------------------------------------------------
Dtmpnofb.txt | 63---------------------------------------------------------------
RLumidify_Casual.ttf -> unused/Lumidify_Casual.ttf | 0
Rgap_buffer.h -> unused/gap_buffer.h | 0
Rmain.c -> unused/main.c | 0
Rstack.h -> unused/stack.h | 0
Rtext-hb.c -> unused/text-hb.c | 0
Rtext-hb.h -> unused/text-hb.h | 0
Rtext.c -> unused/text.c | 0
Rtext.c.bak -> unused/text.c.bak | 0
Rtext.h -> unused/text.h | 0
Rtext/Awami_beta3.ttf -> unused/text/Awami_beta3.ttf | 0
Rtext/FONTLOG.txt -> unused/text/FONTLOG.txt | 0
Rtext/GENTIUM-FAQ.txt -> unused/text/GENTIUM-FAQ.txt | 0
Rtext/GentiumPlus-I.ttf -> unused/text/GentiumPlus-I.ttf | 0
Rtext/GentiumPlus-R.ttf -> unused/text/GentiumPlus-R.ttf | 0
Rtext/LICENSE_OFL.txt -> unused/text/LICENSE_OFL.txt | 0
Rtext/Makefile -> unused/text/Makefile | 0
Rtext/NotoNastaliqUrdu-Regular.ttf -> unused/text/NotoNastaliqUrdu-Regular.ttf | 0
Rtext/OFL-FAQ.txt -> unused/text/OFL-FAQ.txt | 0
Rtext/OFL.txt -> unused/text/OFL.txt | 0
Rtext/README -> unused/text/README | 0
Rtext/README.txt -> unused/text/README.txt | 0
Rtext/bob.c -> unused/text/bob.c | 0
Rtext/font.ttf -> unused/text/font.ttf | 0
Rtext/font1.ttf -> unused/text/font1.ttf | 0
Rtext/font2.ttf -> unused/text/font2.ttf | 0
Rtext/hashtest.c -> unused/text/hashtest.c | 0
Rtext/khash.h -> unused/text/khash.h | 0
Rtext/main.c -> unused/text/main.c | 0
Rtext/main1.c -> unused/text/main1.c | 0
Rtext/new.c -> unused/text/new.c | 0
Rtext/stb_image_write.h -> unused/text/stb_image_write.h | 0
Rtext/stb_truetype.h -> unused/text/stb_truetype.h | 0
Rtext/test.c -> unused/text/test.c | 0
Rtext/test23.c -> unused/text/test23.c | 0
Rtext/test3.c -> unused/text/test3.c | 0
Rtext/text-hb.c -> unused/text/text-hb.c | 0
Rtext/text-hb.new.c -> unused/text/text-hb.new.c | 0
Rtext/text-hb.ubernew.c -> unused/text/text-hb.ubernew.c | 0
Rtext/text-hb.uberubernew.c -> unused/text/text-hb.uberubernew.c | 0
Rtext/text.c -> unused/text/text.c | 0
Rtext/text1.c -> unused/text/text1.c | 0
Rtext/text2.c -> unused/text/text2.c | 0
Rtext/tmp.c -> unused/text/tmp.c | 0
Rtext/utf8.c -> unused/text/utf8.c | 0
Rtext/utf8.h -> unused/text/utf8.h | 0
Rtext/utf8_new.c -> unused/text/utf8_new.c | 0
Rtheme.c -> unused/theme.c | 0
Rtheme.h -> unused/theme.h | 0
62 files changed, 420 insertions(+), 550 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,7 +1,7 @@ LIBS = -lm `pkg-config --libs x11 harfbuzz fontconfig fribidi` STD = -std=c99 CFLAGS = -g -w -fcommon -Wall -Werror -Wextra `pkg-config --cflags x11 harfbuzz fontconfig fribidi` -pedantic -OBJ = stb_truetype.o text_edit.o text-common.o text_buffer.o ltk.o ini.o grid.o button.o test1.o +OBJ = stb_truetype.o text_edit.o text_common.o text_buffer.o ltk.o ini.o grid.o button.o test1.o test1: $(OBJ) gcc $(STD) -o $@ $(OBJ) $(LIBS) diff --git a/button.c b/button.c @@ -31,7 +31,7 @@ #include <fribidi.h> #include <harfbuzz/hb.h> #include <fontconfig/fontconfig.h> -#include "text-common.h" +#include "text_common.h" #include "array.h" #include "text_buffer.h" #include "button.h" diff --git a/ltk.c b/ltk.c @@ -32,8 +32,9 @@ #include <fribidi.h> #include <harfbuzz/hb.h> #include <fontconfig/fontconfig.h> -#include "text-common.h" -#include "text-hb.h" +#include "array.h" +#include "text_common.h" +#include "text_buffer.h" Ltk *ltk_global; diff --git a/ltkx.h b/ltkx.h @@ -8,7 +8,7 @@ #include <fribidi.h> #include <harfbuzz/hb.h> #include <harfbuzz/hb-ot.h> -#include "text-common.h" +#include "text_common.h" #include "button.h" #include "grid.h" #include "array.h" diff --git a/temp b/temp @@ -1 +0,0 @@ -https://tronche.com/gui/x/xlib/window-information/XGetGeometry.html diff --git a/test1.c b/test1.c @@ -42,6 +42,6 @@ int main(int argc, char *argv[]) LtkTextEdit *edit = ltk_create_text_edit(window1, "ہمارے بارے میں blabla bla"); LtkButton *button4 = ltk_create_button(window1, "ہمارے بارے میں blablabla", &bob3, edit); ltk_grid_widget(button4, grid1, 1, 0, 1, 1, LTK_STICKY_TOP | LTK_STICKY_BOTTOM | LTK_STICKY_RIGHT); - ltk_grid_widget(edit, grid1, 1, 1, 1, 1, LTK_STICKY_LEFT | LTK_STICKY_TOP | LTK_STICKY_RIGHT); + ltk_grid_widget(edit, grid1, 1, 1, 1, 1, LTK_STICKY_LEFT | LTK_STICKY_BOTTOM | LTK_STICKY_TOP | LTK_STICKY_RIGHT); ltk_mainloop(); } diff --git a/text-common.c b/text-common.c @@ -1,410 +0,0 @@ -/* - * This file is part of the Lumidify ToolKit (LTK) - * Copyright (c) 2017, 2018, 2020 lumidify <nobody@lumidify.org> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <limits.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include "stb_truetype.h" /* http://nothings.org/stb/stb_truetype.h */ -#include <fontconfig/fontconfig.h> -#include "khash.h" -#include <fribidi.h> -#include <harfbuzz/hb.h> -#include <harfbuzz/hb-ot.h> -#include "text-common.h" -#include "ltk.h" - -extern Ltk *ltk_global; - -/* These unicode routines are taken from - * https://github.com/JeffBezanson/cutef8 */ - -/* is c the start of a utf8 sequence? */ -#define isutf(c) (((c)&0xC0)!=0x80) - -static const uint32_t offsetsFromUTF8[6] = { - 0x00000000UL, 0x00003080UL, 0x000E2080UL, - 0x03C82080UL, 0xFA082080UL, 0x82082080UL -}; - -/* next character without NUL character terminator */ -uint32_t u8_nextmemchar(const char *s, size_t *i) -{ - uint32_t ch = 0; - size_t sz = 0; - do { - ch <<= 6; - ch += (unsigned char)s[(*i)++]; - sz++; - } while (!isutf(s[*i])); - ch -= offsetsFromUTF8[sz-1]; - - return ch; -} - -/* number of characters in NUL-terminated string */ -size_t u8_strlen(const char *s) -{ - size_t count = 0; - size_t i = 0, lasti; - - while (1) { - lasti = i; - while (s[i] > 0) - i++; - count += (i-lasti); - if (s[i++]==0) break; - (void)(isutf(s[++i]) || isutf(s[++i]) || ++i); - count++; - } - return count; -} - -size_t u8_wc_toutf8(char *dest, uint32_t ch) -{ - if (ch < 0x80) { - dest[0] = (char)ch; - return 1; - } - if (ch < 0x800) { - dest[0] = (ch>>6) | 0xC0; - dest[1] = (ch & 0x3F) | 0x80; - return 2; - } - if (ch < 0x10000) { - dest[0] = (ch>>12) | 0xE0; - dest[1] = ((ch>>6) & 0x3F) | 0x80; - dest[2] = (ch & 0x3F) | 0x80; - return 3; - } - if (ch < 0x110000) { - dest[0] = (ch>>18) | 0xF0; - dest[1] = ((ch>>12) & 0x3F) | 0x80; - dest[2] = ((ch>>6) & 0x3F) | 0x80; - dest[3] = (ch & 0x3F) | 0x80; - return 4; - } - return 0; -} - -LtkTextManager * -ltk_init_text(char *font_name) -{ - LtkTextManager *tm = malloc(sizeof(LtkTextManager)); - if (!tm) { - (void)printf("Memory exhausted when trying to create text manager."); - exit(1); - } - tm->font_paths = kh_init(fontid); - tm->font_cache = kh_init(fontstruct); - tm->glyph_cache = kh_init(glyphcache); - /* FIXME: THIS REALLY SHOULD NOT BE UINT16_T! IT GETS MESSY WITH BIT-SHIFTING */ - tm->font_id_cur = 1; - ltk_load_default_font(tm, font_name); - - return tm; -} - -void -ltk_destroy_text_manager(LtkTextManager *tm) -{ - int k; - - kh_destroy(fontid, tm->font_paths); - - for (k = kh_begin(tm->font_cache); k != kh_end(tm->font_cache); k++) { - if (kh_exist(tm->font_cache, k)) { - ltk_destroy_font(kh_value(tm->font_cache, k)); - } - } - kh_destroy(fontstruct, tm->font_cache); - - for (k = kh_begin(tm->glyph_cache); k != kh_end(tm->glyph_cache); k++) { - if (kh_exist(tm->glyph_cache, k)) { - ltk_destroy_glyph_cache(kh_value(tm->glyph_cache, k)); - } - } - kh_destroy(glyphcache, tm->glyph_cache); - - free(tm); -} - -LtkGlyphInfo * -ltk_create_glyph_info(LtkFont *font, unsigned int id, float scale) -{ - LtkGlyphInfo *glyph = malloc(sizeof(LtkGlyphInfo)); - if (!glyph) { - (void)printf("Out of memory!\n"); - exit(1); - } - - glyph->id = id; - glyph->refs = 0; - glyph->alphamap = stbtt_GetGlyphBitmap( - &font->info, scale, scale, id, &glyph->w, - &glyph->h, &glyph->xoff, &glyph->yoff - ); - - return glyph; -} - -void -ltk_destroy_glyph_info(LtkGlyphInfo *gi) -{ - free(gi->alphamap); - free(gi); -} - -LtkGlyphInfo * -ltk_get_glyph_info(LtkFont *font, unsigned int id, float scale, khash_t(glyphinfo) *cache) -{ - int ret; - khint_t k; - LtkGlyphInfo *glyph; - k = kh_get(glyphinfo, cache, id); - if (k == kh_end(cache)) { - glyph = ltk_create_glyph_info(font, id, scale); - /* FIXME: error checking with ret */ - k = kh_put(glyphinfo, cache, id, &ret); - kh_value(cache, k) = glyph; - } else { - glyph = kh_value(cache, k); - } - - return glyph; -} - -khint_t -ltk_create_glyph_cache(LtkTextManager *tm, uint16_t font_id, uint16_t font_size) -{ - khash_t(glyphinfo) *cache = kh_init(glyphinfo); - int ret; - khint_t k; - /* I guess I can just ignore ret for now */ - k = kh_put(glyphcache, tm->glyph_cache, font_id << 16 + font_size, &ret); - kh_value(tm->glyph_cache, k) = cache; - - return k; -} - -void -ltk_destroy_glyph_cache(khash_t(glyphinfo) *cache) -{ - int k; - for (k = kh_begin(cache); k != kh_end(cache); k++) { - if (kh_exist(cache, k)) { - ltk_destroy_glyph_info(kh_value(cache, k)); - } - } - kh_destroy(glyphinfo, cache); -} - -void -ltk_load_default_font(LtkTextManager *tm, char *name) -{ - FcPattern *match; - FcResult result; - char *file; - int index; - uint16_t font; - - tm->fcpattern = FcNameParse(name); - FcPatternAddString(tm->fcpattern, FC_FONTFORMAT, "truetype"); - FcConfigSubstitute(NULL, tm->fcpattern, FcMatchPattern); - FcDefaultSubstitute(tm->fcpattern); - match = FcFontMatch(NULL, tm->fcpattern, &result); - - FcPatternGetString (match, FC_FILE, 0, (FcChar8 **) &file); - /* FIXME: Why is index never used? This is the index within the font file, - so it might be important, although I'm not sure if stb_truetype even - supports it */ - FcPatternGetInteger (match, FC_INDEX, 0, &index); - - tm->default_font = ltk_get_font(tm, file); - - FcPatternDestroy (match); -} - -LtkFont * -ltk_create_font(char *path, uint16_t id) -{ - long len; - LtkFont *font = malloc(sizeof(LtkFont)); - if (!font) { - (void)fprintf(stderr, "Out of memory!\n"); - exit(1); - } - char *contents = ltk_read_file(path, &len); - if (!stbtt_InitFont(&font->info, contents, 0)) - { - (void)fprintf(stderr, "Failed to load font %s\n", path); - exit(1); - } - /* FIXME: make use of the destroy function (last argument to hb_blob_create - see hb-blob.cc in harfbuzz source) */ - hb_blob_t *blob = hb_blob_create(contents, len, HB_MEMORY_MODE_READONLY, NULL, NULL); - hb_face_t *face = hb_face_create(blob, 0); - /* FIXME: need to use destroy function in order for the original file data to be freed? */ - hb_blob_destroy(blob); - font->hb = hb_font_create(face); - hb_face_destroy(face); - hb_ot_font_set_funcs(font->hb); - font->id = id; - font->refs = 0; - - return font; -} - -void -ltk_destroy_font(LtkFont *font) -{ - free(font->info.data); - hb_font_destroy(font->hb); - free(font); -} - -uint16_t -ltk_load_font(LtkTextManager *tm, char *path) -{ - LtkFont *font = ltk_create_font(path, tm->font_id_cur++); - int ret; - khint_t k; - /* FIXME: does kh_destroy also free these copied strings properly? */ - char *key = strdup(path); - k = kh_put(fontid, tm->font_paths, key, &ret); - kh_value(tm->font_paths, k) = font->id; - k = kh_put(fontstruct, tm->font_cache, (khint_t) font->id, &ret); - kh_value(tm->font_cache, k) = font; - k = kh_get(fontid, tm->font_paths, path); - - return font->id; -} - -uint16_t -ltk_get_font(LtkTextManager *tm, char *path) -{ - int ret; - khint_t k; - uint16_t id; - k = kh_get(fontid, tm->font_paths, path); - if (k == kh_end(tm->font_paths)) { - id = ltk_load_font(tm, path); - } else { - id = kh_value(tm->font_paths, k); - } - - return id; -} - -void -ltk_destroy_glyph(LtkGlyph *glyph, khash_t(glyphinfo) *cache) -{ - int k; - if (--glyph->info->refs < 1) { - k = kh_get(glyphinfo, cache, glyph->info->id); - kh_del(glyphinfo, cache, k); - ltk_destroy_glyph_info(glyph->info); - } - free(glyph); -} - -#if 0 -/* based on http://codemadness.org/git/dwm-font/file/drw.c.html#l315 */ -XImage * -ltk_render_text_line( - LtkTextLine *tl, - Display *dpy, - Window window, - GC gc, - Colormap colormap, - XColor fg, - XColor bg) -{ - XWindowAttributes attrs; - XGetWindowAttributes(dpy, window, &attrs); - int depth = attrs.depth; - XImage *img = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, NULL, tl->w, tl->h, 32, 0); - img->data = calloc(img->bytes_per_line, img->height); - XInitImage(img); - int b; - for (int i = 0; i < tl->h; i++) { - b = img->bytes_per_line * i; - for (int j = 0; j < tl->w; j++) { - img->data[b++] = bg.blue / 257; - img->data[b++] = bg.green / 257; - img->data[b++] = bg.red / 257; - b++; - } - } - - LtkTextSegment *ts = tl->start_segment; - int x = 0; - int y = 0; - int is_hor = HB_DIRECTION_IS_HORIZONTAL(ts->dir); - do { - if (is_hor) { - y = tl->h - tl->y_max; - ltk_render_text_segment(ts, x + ts->start_x, y, img, fg); - x += ts->w; - } else { - x = tl->w - tl->x_max; - ltk_render_text_segment(ts, x, y + ts->start_y, img, fg); - y += ts->h; - } - } while (ts = ts->next); - - return img; -} - -void -ltk_render_text_segment( - LtkTextSegment *ts, - unsigned int start_x, - unsigned int start_y, - XImage *img, - XColor fg) -{ - LtkGlyph *glyph = ts->start_glyph; - int x_cur = start_x; - int y_cur = start_y; - int x, y; - double a; - int b; - do { - x = x_cur + glyph->info->xoff + glyph->x_offset; - y = y_cur + glyph->info->yoff - glyph->y_offset; - for (int i = 0; i < glyph->info->h; i++) { - for (int j = 0; j < glyph->info->w; j++) { - b = (y + i) * img->bytes_per_line + (x + j) * 4; - a = glyph->info->alphamap[i * glyph->info->w + j] / 255.0; - img->data[b] = (fg.blue * a + (1 - a) * (uint16_t)img->data[b] * 257) / 257; - img->data[b + 1] = (fg.green * a + (1 - a) * (uint16_t)img->data[b + 1] * 257) / 257; - img->data[b + 2] = (fg.red * a + (1 - a) * (uint16_t)img->data[b + 2] * 257) / 257; - } - } - x_cur += glyph->x_advance; - y_cur -= glyph->y_advance; - } while (glyph = glyph->next); -} -#endif diff --git a/text_buffer.c b/text_buffer.c @@ -34,7 +34,7 @@ #include <fribidi.h> #include <harfbuzz/hb.h> #include <harfbuzz/hb-ot.h> -#include "text-common.h" +#include "text_common.h" #include "array.h" #include "text_buffer.h" #include "ltk.h" diff --git a/text_buffer.h b/text_buffer.h @@ -28,7 +28,7 @@ Requires the following includes: <X11/Xlib.h>, <X11/Xutil.h>, "stb_truetype.h", "khash.h", <harfbuzz/hb.h>, <fribidi.h>, -<fontconfig/fontconfig.h> +<fontconfig/fontconfig.h>, "text_common.h" */ /* Note: hb_script_t and FriBidiLevel are really just uint32_t's, but diff --git a/text_common.c b/text_common.c @@ -0,0 +1,410 @@ +/* + * This file is part of the Lumidify ToolKit (LTK) + * Copyright (c) 2017, 2018, 2020 lumidify <nobody@lumidify.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <limits.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "stb_truetype.h" /* http://nothings.org/stb/stb_truetype.h */ +#include <fontconfig/fontconfig.h> +#include "khash.h" +#include <fribidi.h> +#include <harfbuzz/hb.h> +#include <harfbuzz/hb-ot.h> +#include "text_common.h" +#include "ltk.h" + +extern Ltk *ltk_global; + +/* These unicode routines are taken from + * https://github.com/JeffBezanson/cutef8 */ + +/* is c the start of a utf8 sequence? */ +#define isutf(c) (((c)&0xC0)!=0x80) + +static const uint32_t offsetsFromUTF8[6] = { + 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL +}; + +/* next character without NUL character terminator */ +uint32_t u8_nextmemchar(const char *s, size_t *i) +{ + uint32_t ch = 0; + size_t sz = 0; + do { + ch <<= 6; + ch += (unsigned char)s[(*i)++]; + sz++; + } while (!isutf(s[*i])); + ch -= offsetsFromUTF8[sz-1]; + + return ch; +} + +/* number of characters in NUL-terminated string */ +size_t u8_strlen(const char *s) +{ + size_t count = 0; + size_t i = 0, lasti; + + while (1) { + lasti = i; + while (s[i] > 0) + i++; + count += (i-lasti); + if (s[i++]==0) break; + (void)(isutf(s[++i]) || isutf(s[++i]) || ++i); + count++; + } + return count; +} + +size_t u8_wc_toutf8(char *dest, uint32_t ch) +{ + if (ch < 0x80) { + dest[0] = (char)ch; + return 1; + } + if (ch < 0x800) { + dest[0] = (ch>>6) | 0xC0; + dest[1] = (ch & 0x3F) | 0x80; + return 2; + } + if (ch < 0x10000) { + dest[0] = (ch>>12) | 0xE0; + dest[1] = ((ch>>6) & 0x3F) | 0x80; + dest[2] = (ch & 0x3F) | 0x80; + return 3; + } + if (ch < 0x110000) { + dest[0] = (ch>>18) | 0xF0; + dest[1] = ((ch>>12) & 0x3F) | 0x80; + dest[2] = ((ch>>6) & 0x3F) | 0x80; + dest[3] = (ch & 0x3F) | 0x80; + return 4; + } + return 0; +} + +LtkTextManager * +ltk_init_text(char *font_name) +{ + LtkTextManager *tm = malloc(sizeof(LtkTextManager)); + if (!tm) { + (void)printf("Memory exhausted when trying to create text manager."); + exit(1); + } + tm->font_paths = kh_init(fontid); + tm->font_cache = kh_init(fontstruct); + tm->glyph_cache = kh_init(glyphcache); + /* FIXME: THIS REALLY SHOULD NOT BE UINT16_T! IT GETS MESSY WITH BIT-SHIFTING */ + tm->font_id_cur = 1; + ltk_load_default_font(tm, font_name); + + return tm; +} + +void +ltk_destroy_text_manager(LtkTextManager *tm) +{ + int k; + + kh_destroy(fontid, tm->font_paths); + + for (k = kh_begin(tm->font_cache); k != kh_end(tm->font_cache); k++) { + if (kh_exist(tm->font_cache, k)) { + ltk_destroy_font(kh_value(tm->font_cache, k)); + } + } + kh_destroy(fontstruct, tm->font_cache); + + for (k = kh_begin(tm->glyph_cache); k != kh_end(tm->glyph_cache); k++) { + if (kh_exist(tm->glyph_cache, k)) { + ltk_destroy_glyph_cache(kh_value(tm->glyph_cache, k)); + } + } + kh_destroy(glyphcache, tm->glyph_cache); + + free(tm); +} + +LtkGlyphInfo * +ltk_create_glyph_info(LtkFont *font, unsigned int id, float scale) +{ + LtkGlyphInfo *glyph = malloc(sizeof(LtkGlyphInfo)); + if (!glyph) { + (void)printf("Out of memory!\n"); + exit(1); + } + + glyph->id = id; + glyph->refs = 0; + glyph->alphamap = stbtt_GetGlyphBitmap( + &font->info, scale, scale, id, &glyph->w, + &glyph->h, &glyph->xoff, &glyph->yoff + ); + + return glyph; +} + +void +ltk_destroy_glyph_info(LtkGlyphInfo *gi) +{ + free(gi->alphamap); + free(gi); +} + +LtkGlyphInfo * +ltk_get_glyph_info(LtkFont *font, unsigned int id, float scale, khash_t(glyphinfo) *cache) +{ + int ret; + khint_t k; + LtkGlyphInfo *glyph; + k = kh_get(glyphinfo, cache, id); + if (k == kh_end(cache)) { + glyph = ltk_create_glyph_info(font, id, scale); + /* FIXME: error checking with ret */ + k = kh_put(glyphinfo, cache, id, &ret); + kh_value(cache, k) = glyph; + } else { + glyph = kh_value(cache, k); + } + + return glyph; +} + +khint_t +ltk_create_glyph_cache(LtkTextManager *tm, uint16_t font_id, uint16_t font_size) +{ + khash_t(glyphinfo) *cache = kh_init(glyphinfo); + int ret; + khint_t k; + /* I guess I can just ignore ret for now */ + k = kh_put(glyphcache, tm->glyph_cache, font_id << 16 + font_size, &ret); + kh_value(tm->glyph_cache, k) = cache; + + return k; +} + +void +ltk_destroy_glyph_cache(khash_t(glyphinfo) *cache) +{ + int k; + for (k = kh_begin(cache); k != kh_end(cache); k++) { + if (kh_exist(cache, k)) { + ltk_destroy_glyph_info(kh_value(cache, k)); + } + } + kh_destroy(glyphinfo, cache); +} + +void +ltk_load_default_font(LtkTextManager *tm, char *name) +{ + FcPattern *match; + FcResult result; + char *file; + int index; + uint16_t font; + + tm->fcpattern = FcNameParse(name); + FcPatternAddString(tm->fcpattern, FC_FONTFORMAT, "truetype"); + FcConfigSubstitute(NULL, tm->fcpattern, FcMatchPattern); + FcDefaultSubstitute(tm->fcpattern); + match = FcFontMatch(NULL, tm->fcpattern, &result); + + FcPatternGetString (match, FC_FILE, 0, (FcChar8 **) &file); + /* FIXME: Why is index never used? This is the index within the font file, + so it might be important, although I'm not sure if stb_truetype even + supports it */ + FcPatternGetInteger (match, FC_INDEX, 0, &index); + + tm->default_font = ltk_get_font(tm, file); + + FcPatternDestroy (match); +} + +LtkFont * +ltk_create_font(char *path, uint16_t id) +{ + long len; + LtkFont *font = malloc(sizeof(LtkFont)); + if (!font) { + (void)fprintf(stderr, "Out of memory!\n"); + exit(1); + } + char *contents = ltk_read_file(path, &len); + if (!stbtt_InitFont(&font->info, contents, 0)) + { + (void)fprintf(stderr, "Failed to load font %s\n", path); + exit(1); + } + /* FIXME: make use of the destroy function (last argument to hb_blob_create - see hb-blob.cc in harfbuzz source) */ + hb_blob_t *blob = hb_blob_create(contents, len, HB_MEMORY_MODE_READONLY, NULL, NULL); + hb_face_t *face = hb_face_create(blob, 0); + /* FIXME: need to use destroy function in order for the original file data to be freed? */ + hb_blob_destroy(blob); + font->hb = hb_font_create(face); + hb_face_destroy(face); + hb_ot_font_set_funcs(font->hb); + font->id = id; + font->refs = 0; + + return font; +} + +void +ltk_destroy_font(LtkFont *font) +{ + free(font->info.data); + hb_font_destroy(font->hb); + free(font); +} + +uint16_t +ltk_load_font(LtkTextManager *tm, char *path) +{ + LtkFont *font = ltk_create_font(path, tm->font_id_cur++); + int ret; + khint_t k; + /* FIXME: does kh_destroy also free these copied strings properly? */ + char *key = strdup(path); + k = kh_put(fontid, tm->font_paths, key, &ret); + kh_value(tm->font_paths, k) = font->id; + k = kh_put(fontstruct, tm->font_cache, (khint_t) font->id, &ret); + kh_value(tm->font_cache, k) = font; + k = kh_get(fontid, tm->font_paths, path); + + return font->id; +} + +uint16_t +ltk_get_font(LtkTextManager *tm, char *path) +{ + int ret; + khint_t k; + uint16_t id; + k = kh_get(fontid, tm->font_paths, path); + if (k == kh_end(tm->font_paths)) { + id = ltk_load_font(tm, path); + } else { + id = kh_value(tm->font_paths, k); + } + + return id; +} + +void +ltk_destroy_glyph(LtkGlyph *glyph, khash_t(glyphinfo) *cache) +{ + int k; + if (--glyph->info->refs < 1) { + k = kh_get(glyphinfo, cache, glyph->info->id); + kh_del(glyphinfo, cache, k); + ltk_destroy_glyph_info(glyph->info); + } + free(glyph); +} + +#if 0 +/* based on http://codemadness.org/git/dwm-font/file/drw.c.html#l315 */ +XImage * +ltk_render_text_line( + LtkTextLine *tl, + Display *dpy, + Window window, + GC gc, + Colormap colormap, + XColor fg, + XColor bg) +{ + XWindowAttributes attrs; + XGetWindowAttributes(dpy, window, &attrs); + int depth = attrs.depth; + XImage *img = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, NULL, tl->w, tl->h, 32, 0); + img->data = calloc(img->bytes_per_line, img->height); + XInitImage(img); + int b; + for (int i = 0; i < tl->h; i++) { + b = img->bytes_per_line * i; + for (int j = 0; j < tl->w; j++) { + img->data[b++] = bg.blue / 257; + img->data[b++] = bg.green / 257; + img->data[b++] = bg.red / 257; + b++; + } + } + + LtkTextSegment *ts = tl->start_segment; + int x = 0; + int y = 0; + int is_hor = HB_DIRECTION_IS_HORIZONTAL(ts->dir); + do { + if (is_hor) { + y = tl->h - tl->y_max; + ltk_render_text_segment(ts, x + ts->start_x, y, img, fg); + x += ts->w; + } else { + x = tl->w - tl->x_max; + ltk_render_text_segment(ts, x, y + ts->start_y, img, fg); + y += ts->h; + } + } while (ts = ts->next); + + return img; +} + +void +ltk_render_text_segment( + LtkTextSegment *ts, + unsigned int start_x, + unsigned int start_y, + XImage *img, + XColor fg) +{ + LtkGlyph *glyph = ts->start_glyph; + int x_cur = start_x; + int y_cur = start_y; + int x, y; + double a; + int b; + do { + x = x_cur + glyph->info->xoff + glyph->x_offset; + y = y_cur + glyph->info->yoff - glyph->y_offset; + for (int i = 0; i < glyph->info->h; i++) { + for (int j = 0; j < glyph->info->w; j++) { + b = (y + i) * img->bytes_per_line + (x + j) * 4; + a = glyph->info->alphamap[i * glyph->info->w + j] / 255.0; + img->data[b] = (fg.blue * a + (1 - a) * (uint16_t)img->data[b] * 257) / 257; + img->data[b + 1] = (fg.green * a + (1 - a) * (uint16_t)img->data[b + 1] * 257) / 257; + img->data[b + 2] = (fg.red * a + (1 - a) * (uint16_t)img->data[b + 2] * 257) / 257; + } + } + x_cur += glyph->x_advance; + y_cur -= glyph->y_advance; + } while (glyph = glyph->next); +} +#endif diff --git a/text-common.h b/text_common.h diff --git a/text_edit.c b/text_edit.c @@ -31,7 +31,7 @@ #include <fribidi.h> #include <harfbuzz/hb.h> #include <fontconfig/fontconfig.h> -#include "text-common.h" +#include "text_common.h" #include "array.h" #include "text_buffer.h" #include "text_edit.h" diff --git a/tmpfb.txt b/tmpfb.txt @@ -1,67 +0,0 @@ -49 -27 -6d -20 -61 -20 -62 -75 -74 -74 -6f -6e -21 -0 -49 -27 -6d -20 -61 -20 -62 -75 -74 -74 -6f -6e -21 -0 -49 -27 -6d -20 -61 -20 -62 -75 -74 -74 -6f -6e -21 -0 -6c1 -645 -627 -631 -6d2 -20 -628 -627 -631 -6d2 -20 -645 -6cc -6ba -20 -62 -6c -61 -62 -6c -61 -62 -6c -61 -0 diff --git a/tmpnofb.txt b/tmpnofb.txt @@ -1,63 +0,0 @@ -49 -27 -6d -20 -61 -20 -62 -75 -74 -74 -6f -6e -21 -0 -49 -27 -6d -20 -61 -20 -62 -75 -74 -74 -6f -6e -21 -0 -49 -27 -6d -20 -61 -20 -62 -75 -74 -74 -6f -6e -21 -0 -62 -6c -61 -62 -6c -61 -62 -6c -61 -20 -fb9f -fbff -fee3 -20 -fbae -fead -fe8e -fe91 -20 -fbae -fead diff --git a/Lumidify_Casual.ttf b/unused/Lumidify_Casual.ttf Binary files differ. diff --git a/gap_buffer.h b/unused/gap_buffer.h diff --git a/main.c b/unused/main.c diff --git a/stack.h b/unused/stack.h diff --git a/text-hb.c b/unused/text-hb.c diff --git a/text-hb.h b/unused/text-hb.h diff --git a/text.c b/unused/text.c diff --git a/text.c.bak b/unused/text.c.bak diff --git a/text.h b/unused/text.h diff --git a/text/Awami_beta3.ttf b/unused/text/Awami_beta3.ttf Binary files differ. diff --git a/text/FONTLOG.txt b/unused/text/FONTLOG.txt diff --git a/text/GENTIUM-FAQ.txt b/unused/text/GENTIUM-FAQ.txt diff --git a/text/GentiumPlus-I.ttf b/unused/text/GentiumPlus-I.ttf Binary files differ. diff --git a/text/GentiumPlus-R.ttf b/unused/text/GentiumPlus-R.ttf Binary files differ. diff --git a/text/LICENSE_OFL.txt b/unused/text/LICENSE_OFL.txt diff --git a/text/Makefile b/unused/text/Makefile diff --git a/text/NotoNastaliqUrdu-Regular.ttf b/unused/text/NotoNastaliqUrdu-Regular.ttf Binary files differ. diff --git a/text/OFL-FAQ.txt b/unused/text/OFL-FAQ.txt diff --git a/text/OFL.txt b/unused/text/OFL.txt diff --git a/text/README b/unused/text/README diff --git a/text/README.txt b/unused/text/README.txt diff --git a/text/bob.c b/unused/text/bob.c diff --git a/text/font.ttf b/unused/text/font.ttf Binary files differ. diff --git a/text/font1.ttf b/unused/text/font1.ttf Binary files differ. diff --git a/text/font2.ttf b/unused/text/font2.ttf Binary files differ. diff --git a/text/hashtest.c b/unused/text/hashtest.c diff --git a/text/khash.h b/unused/text/khash.h diff --git a/text/main.c b/unused/text/main.c diff --git a/text/main1.c b/unused/text/main1.c diff --git a/text/new.c b/unused/text/new.c diff --git a/text/stb_image_write.h b/unused/text/stb_image_write.h diff --git a/text/stb_truetype.h b/unused/text/stb_truetype.h diff --git a/text/test.c b/unused/text/test.c diff --git a/text/test23.c b/unused/text/test23.c diff --git a/text/test3.c b/unused/text/test3.c diff --git a/text/text-hb.c b/unused/text/text-hb.c diff --git a/text/text-hb.new.c b/unused/text/text-hb.new.c diff --git a/text/text-hb.ubernew.c b/unused/text/text-hb.ubernew.c diff --git a/text/text-hb.uberubernew.c b/unused/text/text-hb.uberubernew.c diff --git a/text/text.c b/unused/text/text.c diff --git a/text/text1.c b/unused/text/text1.c diff --git a/text/text2.c b/unused/text/text2.c diff --git a/text/tmp.c b/unused/text/tmp.c diff --git a/text/utf8.c b/unused/text/utf8.c diff --git a/text/utf8.h b/unused/text/utf8.h diff --git a/text/utf8_new.c b/unused/text/utf8_new.c diff --git a/theme.c b/unused/theme.c diff --git a/theme.h b/unused/theme.h