aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2019-02-01 15:04:31 +0100
committerGerd Hoffmann <kraxel@redhat.com>2019-02-01 15:04:31 +0100
commitb66dd9317009b665aeaa0ce7ecf097c56af90a04 (patch)
tree7a3791507ffc1e3868ff518a535a1211433165ea
parentb69070ae5ab12189df3130a0ec236ebdcf148551 (diff)
downloadfbida-b66dd9317009b665aeaa0ce7ecf097c56af90a04.tar.gz
use cairo for text rendering
-rw-r--r--fb-gui.c209
-rw-r--r--fb-gui.h13
-rw-r--r--fbi.c94
-rw-r--r--meson.build5
4 files changed, 76 insertions, 245 deletions
diff --git a/fb-gui.c b/fb-gui.c
index 46b8d69..654e369 100644
--- a/fb-gui.c
+++ b/fb-gui.c
@@ -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;
}
diff --git a/fb-gui.h b/fb-gui.h
index fa55692..3bb1eba 100644
--- a/fb-gui.h
+++ b/fb-gui.h
@@ -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);
diff --git a/fbi.c b/fbi.c
index d00b843..7ac6d63 100644
--- a/fbi.c
+++ b/fbi.c
@@ -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 ]