diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2019-02-01 15:04:31 +0100 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2019-02-01 15:04:31 +0100 |
commit | b66dd9317009b665aeaa0ce7ecf097c56af90a04 (patch) | |
tree | 7a3791507ffc1e3868ff518a535a1211433165ea | |
parent | b69070ae5ab12189df3130a0ec236ebdcf148551 (diff) | |
download | fbida-b66dd9317009b665aeaa0ce7ecf097c56af90a04.tar.gz |
use cairo for text rendering
-rw-r--r-- | fb-gui.c | 209 | ||||
-rw-r--r-- | fb-gui.h | 13 | ||||
-rw-r--r-- | fbi.c | 94 | ||||
-rw-r--r-- | meson.build | 5 |
4 files changed, 76 insertions, 245 deletions
@@ -8,10 +8,6 @@ #include <sys/ioctl.h> #include <linux/fb.h> -#include <cairo.h> -#include <fontconfig/fontconfig.h> -#include <fontconfig/fcfreetype.h> - #include "vt.h" #include "fbtools.h" #include "fb-gui.h" @@ -30,6 +26,7 @@ static unsigned int *sdirty,swidth,sheight; static cairo_t *context; static cairo_surface_t *surface; static unsigned char *framebuffer; +static cairo_font_extents_t extents; static void shadow_lut_init_one(int32_t *lut, int bits, int shift) { @@ -252,220 +249,64 @@ void shadow_darkify(int x1, int x2, int y1,int y2, int percent) cairo_fill(context); } -/* ---------------------------------------------------------------------- */ -/* shadow framebuffer -- text rendering */ - -static void shadow_draw_glyph(FT_Bitmap *bitmap, int sx, int sy) -{ - unsigned char *src,*dst; - unsigned int bit; - int x,y; - - src = bitmap->buffer; - for (y = 0; y < bitmap->rows; y++, src += bitmap->pitch) { - if (sy+y < 0) - continue; - if (sy+y >= sheight) - continue; - sdirty[sy+y]++; - dst = shadow[sy+y] + sx*4; - switch (bitmap->pixel_mode) { - case FT_PIXEL_MODE_MONO: - for (x = 0; x < bitmap->width; x++, dst += 4) { - if (sx+x < 0) - continue; - if (sx+x >= swidth) - continue; - bit = (1 << (7-(x&7))); - if (bit & (src[x >> 3])) { - dst[0] = 255; - dst[1] = 255; - dst[2] = 255; - } - } - break; - case FT_PIXEL_MODE_GRAY: - for (x = 0; x < bitmap->width; x++, dst += 4) { - if (sx+x < 0) - continue; - if (sx+x >= swidth) - continue; - if (src[x]) { - dst[0] += (255-dst[0]) * src[x] / 255; - dst[1] += (255-dst[1]) * src[x] / 255; - dst[2] += (255-dst[2]) * src[x] / 255; - } - } - break; - } - } -} - -struct glyph { - FT_Glyph glyph; - int pos; -}; - -int shadow_draw_string(FT_Face face, int x, int y, wchar_t *str, int align) +int shadow_draw_string(int x, int y, char *str, int align) { - struct glyph *glyphs; - FT_UInt gi,pgi; - FT_Vector delta,pen; - FT_Glyph image; - FT_BitmapGlyph bit; - size_t len; - int i,ng,pos; - int kerning; - - len = wcslen(str); - glyphs = malloc(sizeof(*glyphs) * len); - memset(glyphs,0,sizeof(*glyphs) * len); - - kerning = FT_HAS_KERNING(face); - pgi = 0; - - for (ng = 0, pos = 0, i = 0; str[i] != 0; i++) { - gi = FT_Get_Char_Index(face, str[i]); - if (kerning && pgi && gi) { - FT_Get_Kerning(face,pgi,gi,FT_KERNING_DEFAULT,&delta); - pos += delta.x; - } - glyphs[ng].pos = pos; - if (0 != FT_Load_Glyph(face, gi, FT_LOAD_DEFAULT)) - continue; - if (0 != FT_Get_Glyph(face->glyph, &glyphs[ng].glyph)) - continue; - pos += face->glyph->advance.x; - pgi = gi; - ng++; - } + cairo_text_extents_t te; + cairo_text_extents(context, str, &te); switch(align) { case -1: /* left */ break; case 0: /* center */ - x -= pos >> 7; + x -= te.x_advance / 2; break; case 1: /* right */ - x -= pos >> 6; + x -= te.x_advance; break; } - pen.x = 0; - pen.y = 0; - for (i = 0; i < ng; i++) { - image = glyphs[i].glyph; - if (0 != FT_Glyph_To_Bitmap(&image,FT_RENDER_MODE_NORMAL,&pen,0)) - continue; - bit = (FT_BitmapGlyph)image; - shadow_draw_glyph(&bit->bitmap, - x + bit->left + (glyphs[i].pos >> 6), - y - bit->top); - if (image != glyphs[i].glyph) - FT_Done_Glyph(image); - } - - for (i = 0; i < ng; i++) - FT_Done_Glyph(glyphs[i].glyph); - free(glyphs); - return pos >> 6; + cairo_move_to(context, x, y + extents.ascent); + cairo_show_text(context, str); + return 0; } -void shadow_draw_text_box(FT_Face face, int x, int y, int percent, wchar_t *lines[], unsigned int count) +void shadow_draw_text_box(int x, int y, int percent, char *lines[], unsigned int count) { - unsigned int i,len,max, x1, x2, y1, y2; + unsigned int i, len, max, x1, x2, y1, y2; if (!console_visible) return; max = 0; for (i = 0; i < count; i++) { - len = wcslen(lines[i]); + len = strlen(lines[i]); if (max < len) max = len; } - FT_Load_Glyph(face, FT_Get_Char_Index(face, 'x'), FT_LOAD_DEFAULT); x1 = x; - x2 = x + max * (face->glyph->advance.x >> 6); + x2 = x + max * extents.max_x_advance; y1 = y; - y2 = y + count * (face->size->metrics.height >> 6); + y2 = y + count * extents.height; x += xs; x2 += 2*xs; y += ys; y2 += 2*ys; - y += (face->size->metrics.height >> 6); - y += (face->size->metrics.descender >> 6); - + shadow_darkify(x1, x2, y1, y2, percent); shadow_draw_rect(x1, x2, y1, y2); for (i = 0; i < count; i++) { - shadow_draw_string(face, x, y, lines[i], -1); - y += (face->size->metrics.height >> 6); + shadow_draw_string(x, y, lines[i], -1); + y += extents.height; } } -/* ---------------------------------------------------------------------- */ -/* fontconfig + freetype font rendering */ - -static FT_Library freetype; - -void font_init(void) +cairo_font_extents_t *shadow_font_init(char *font) { - int rc; - - FcInit(); - rc = FT_Init_FreeType(&freetype); - if (rc) { - fprintf(stderr,"FT_Init_FreeType() failed\n"); - exit(1); - } -} - -FT_Face font_open(char *fcname) -{ - FcResult result = 0; - FT_Face face = NULL; - FcPattern *pattern,*match; - char *fontname,*h; - FcChar8 *filename; - double pixelsize; - int rc; - - /* parse + match font name */ - pattern = FcNameParse(fcname); - FcConfigSubstitute(NULL, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - match = FcFontMatch (0, pattern, &result); - FcPatternDestroy(pattern); - if (FcResultMatch != result) - return NULL; - fontname = FcNameUnparse(match); - h = strchr(fontname, ':'); - if (h) - *h = 0; - - /* try get the face directly */ - result = FcPatternGetFTFace(match, FC_FT_FACE, 0, &face); - if (FcResultMatch == result) { - fprintf(stderr,"using \"%s\", face=%p\n",fontname,face); - return face; - } - - /* failing that use the filename */ - result = FcPatternGetString (match, FC_FILE, 0, &filename); - if (FcResultMatch == result) { - result = FcPatternGetDouble(match, FC_PIXEL_SIZE, 0, &pixelsize); - if (FcResultMatch != result) - pixelsize = 16; - fprintf(stderr,"using \"%s\", pixelsize=%.2lf file=%s\n", - fontname,pixelsize,filename); - rc = FT_New_Face (freetype, filename, 0, &face); - if (rc) - return NULL; - FT_Set_Pixel_Sizes(face, 0, (int)pixelsize); - return face; - } - - /* oops, didn't work */ - return NULL; + /* TODO: parse font */ + cairo_select_font_face(context, "monospace", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(context, 16); + cairo_font_extents(context, &extents); + return &extents; } @@ -1,6 +1,4 @@ -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_GLYPH_H +#include <cairo.h> extern int visible; @@ -20,9 +18,8 @@ void shadow_merge_rgbdata(int x, int y, int pixels, int weight, unsigned char *rgb); void shadow_darkify(int x1, int x2, int y1,int y2, int percent); -int shadow_draw_string(FT_Face face, int x, int y, wchar_t *str, int align); -void shadow_draw_text_box(FT_Face face, int x, int y, int percent, - wchar_t *lines[], unsigned int count); +int shadow_draw_string(int x, int y, char *str, int align); +void shadow_draw_text_box(int x, int y, int percent, + char *lines[], unsigned int count); -void font_init(void); -FT_Face font_open(char *fcname); +cairo_font_extents_t *shadow_font_init(char *find); @@ -20,6 +20,7 @@ #include <ctype.h> #include <locale.h> #include <wchar.h> +#include <setjmp.h> #include <sys/time.h> #include <sys/ioctl.h> #include <sys/stat.h> @@ -121,7 +122,7 @@ int interactive = 0; /* font handling */ static char *fontname = NULL; -static FT_Face face; +static cairo_font_extents_t *extents; /* ---------------------------------------------------------------------- */ /* fwd declarations */ @@ -404,7 +405,7 @@ shadow_draw_image(struct ida_image *img, int xoff, int yoff, static void status_prepare(void) { struct ida_image *img = flist_img_get(fcurrent); - int y1 = gfx->vdisplay - (face->size->metrics.height >> 6); + int y1 = gfx->vdisplay - extents->height; int y2 = gfx->vdisplay - 1; if (img) { @@ -418,34 +419,34 @@ static void status_prepare(void) static void status_update(unsigned char *desc, char *info) { - int yt = gfx->vdisplay + (face->size->metrics.descender >> 6); - wchar_t str[128]; + int yt = gfx->vdisplay - extents->height; + char str[128]; if (!statusline) return; status_prepare(); - swprintf(str,ARRAY_SIZE(str),L"%s",desc); - shadow_draw_string(face, 0, yt, str, -1); + snprintf(str,ARRAY_SIZE(str),"%s",desc); + shadow_draw_string(0, yt, str, -1); if (info) { - swprintf(str,ARRAY_SIZE(str), L"[ %s ] H - Help", info); + snprintf(str,ARRAY_SIZE(str), "[ %s ] H - Help", info); } else { - swprintf(str,ARRAY_SIZE(str), L"| H - Help"); + snprintf(str,ARRAY_SIZE(str), "| H - Help"); } - shadow_draw_string(face, gfx->hdisplay, yt, str, 1); + shadow_draw_string(gfx->hdisplay, yt, str, 1); shadow_render(gfx); } static void status_error(unsigned char *msg) { - int yt = gfx->vdisplay + (face->size->metrics.descender >> 6); - wchar_t str[128]; + int yt = gfx->vdisplay - extents->height; + char str[128]; status_prepare(); - swprintf(str,ARRAY_SIZE(str), L"%s", msg); - shadow_draw_string(face, 0, yt, str, -1); + snprintf(str,ARRAY_SIZE(str), "%s", msg); + shadow_draw_string(0, yt, str, -1); shadow_render(gfx); sleep(2); @@ -476,7 +477,7 @@ static void show_exif(struct flist *f) unsigned int tag,l1,l2,len,count,i; const char *title[ARRAY_SIZE(tags)]; char *value[ARRAY_SIZE(tags)]; - wchar_t *linebuffer[ARRAY_SIZE(tags)]; + char *linebuffer[ARRAY_SIZE(tags)]; if (!console_visible) return; @@ -516,13 +517,13 @@ static void show_exif(struct flist *f) if (NULL == title[tag]) continue; linebuffer[count] = malloc(sizeof(wchar_t)*(l1+l2+8)); - swprintf(linebuffer[count], l1+l2+8, - L"%-*.*s : %-*.*s", + snprintf(linebuffer[count], l1+l2+8, + "%-*.*s : %-*.*s", l1, l1, title[tag], l2, l2, value[tag]); count++; } - shadow_draw_text_box(face, 24, 16, transparency, + shadow_draw_text_box(24, 16, transparency, linebuffer, count); shadow_render(gfx); @@ -537,34 +538,34 @@ static void show_exif(struct flist *f) static void show_help(void) { - static wchar_t *help[] = { - L"keyboard commands", - L"~~~~~~~~~~~~~~~~~", - L" cursor keys - scroll image", - L" PgUp, k - previous image", - L" PgDn, SPACE, j - next image", - L" <i>g - jump to image #i", - L"", - L" a - autozoom image", - L" +/- - zoom in/out", - L" <i>s - set zoom to <i>%", - L"", - L" ESC, q - quit", - L" v - toggle statusline", - L" h - show this help text", - L" i - show EXIF info", - L" p - pause slideshow", - L"", - L"available if started with --edit switch,", - L"rotation works for jpeg images only:", - L" D, Shift+d - delete image", - L" r - rotate 90 degrees clockwise", - L" l - rotate 90 degrees counter-clockwise", - L" x - mirror image vertically (top / bottom)", - L" y - mirror image horizontally (left to right)", + static char *help[] = { + "keyboard commands", + "~~~~~~~~~~~~~~~~~", + " cursor keys - scroll image", + " PgUp, k - previous image", + " PgDn, SPACE, j - next image", + " <i>g - jump to image #i", + "", + " a - autozoom image", + " +/- - zoom in/out", + " <i>s - set zoom to <i>%", + "", + " ESC, q - quit", + " v - toggle statusline", + " h - show this help text", + " i - show EXIF info", + " p - pause slideshow", + "", + "available if started with --edit switch,", + "rotation works for jpeg images only:", + " D, Shift+d - delete image", + " r - rotate 90 degrees clockwise", + " l - rotate 90 degrees counter-clockwise", + " x - mirror image vertically (top / bottom)", + " y - mirror image horizontally (left to right)", }; - shadow_draw_text_box(face, 24, 16, transparency, + shadow_draw_text_box(24, 16, transparency, help, ARRAY_SIZE(help)); shadow_render(gfx); } @@ -1314,14 +1315,8 @@ int main(int argc, char *argv[]) flist_randomize(); fcurrent = flist_first(); - font_init(); if (NULL == fontname) fontname = "monospace:size=16"; - face = font_open(fontname); - if (NULL == face) { - fprintf(stderr,"can't open font: %s\n",fontname); - exit(1); - } /* gfx device init */ device = cfg_get_str(O_DEVICE); @@ -1360,6 +1355,7 @@ int main(int argc, char *argv[]) } } shadow_init(gfx); + extents = shadow_font_init(fontname); /* svga main loop */ kbd_init(use_libinput, gfx->devnum); diff --git a/meson.build b/meson.build index e4408b6..4e4b620 100644 --- a/meson.build +++ b/meson.build @@ -14,8 +14,6 @@ x11resrun = run_command('scripts/x11resdir.sh', get_option('prefix')) x11resdir = x11resrun.stdout().strip() # pkg-config deps -freetype_dep = dependency('freetype2') -fontconf_dep = dependency('fontconfig') pixman_dep = dependency('pixman-1') poppler_dep = dependency('poppler-glib') cairo_dep = dependency('cairo') @@ -87,8 +85,7 @@ fbi_srcs = [ 'fbi.c', 'fb-gui.c', 'desktop.c', 'vt.c', 'kbd.c', 'fbtools.c', 'drmtools.c', 'filter.c', 'op.c', 'jpegtools.c', trans_src, read_srcs ] -fbi_deps = [ freetype_dep, fontconf_dep, - drm_dep, pixman_dep, cairo_dep, +fbi_deps = [ drm_dep, pixman_dep, cairo_dep, exif_dep, image_deps, math_dep, udev_dep, input_dep ] |