aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2014-04-18 18:39:56 -0400
committerJesse Luehrs <doy@tozt.net>2014-04-18 18:39:56 -0400
commit5b71f08f1ccd3d08512be8e700af30a6f3c24527 (patch)
tree17f78f8d818d1b67065169defd19c5d4c3df181b
parent9524de2133b5d731987228e3eb297a990af6f2bc (diff)
downloadrunes-5b71f08f1ccd3d08512be8e700af30a6f3c24527.tar.gz
runes-5b71f08f1ccd3d08512be8e700af30a6f3c24527.zip
start laying out text with pango
this breaks bold and italic for the moment, i'll restore that functionality soon. it also doesn't fix positioning of non-ASCII characters yet, but should make it possible to do so in the future.
-rw-r--r--Makefile2
-rw-r--r--display.c104
-rw-r--r--runes.h1
-rw-r--r--term.h3
4 files changed, 48 insertions, 62 deletions
diff --git a/Makefile b/Makefile
index 8c5df71..bdf6871 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
OUT = runes
OBJ = runes.o display.o term.o parser.o window-xlib.o pty-unix.o
-LIBS = cairo cairo-xlib libuv
+LIBS = cairo cairo-xlib libuv pangocairo
CFLAGS ?= -g -Wall -Wextra -Werror
LDFLAGS ?= -g -Wall -Wextra -Werror
diff --git a/display.c b/display.c
index 497f76a..ffed868 100644
--- a/display.c
+++ b/display.c
@@ -3,19 +3,17 @@
#include "runes.h"
-static void runes_display_recalculate_font(RunesTerm *t);
+static void runes_display_recalculate_font_metrics(RunesTerm *t);
static void runes_display_position_cursor(RunesTerm *t, cairo_t *cr);
static void runes_display_paint_rectangle(
RunesTerm *t, cairo_t *cr, cairo_pattern_t *pattern,
int x, int y, int width, int height);
-static cairo_scaled_font_t *runes_display_make_font(RunesTerm *t);
static void runes_display_scroll_down(RunesTerm *t, int rows);
void runes_display_init(RunesTerm *t)
{
- t->font_name = "monospace";
- t->font_size = 14.0;
- runes_display_recalculate_font(t);
+ t->font_name = "monospace 10";
+ runes_display_recalculate_font_metrics(t);
t->colors[0] = cairo_pattern_create_rgb(0.0, 0.0, 0.0);
t->colors[1] = cairo_pattern_create_rgb(1.0, 0.0, 0.0);
@@ -62,7 +60,14 @@ void runes_display_set_window_size(RunesTerm *t)
t->cr = cairo_create(surface);
cairo_surface_destroy(surface);
cairo_set_source(t->cr, t->fgcolor);
- cairo_set_scaled_font(t->cr, t->font);
+ if (t->layout) {
+ pango_cairo_update_layout(t->cr, t->layout);
+ }
+ else {
+ t->layout = pango_cairo_create_layout(t->cr);
+ }
+ pango_layout_set_font_description(
+ t->layout, pango_font_description_from_string(t->font_name));
cairo_save(t->cr);
@@ -114,25 +119,20 @@ void runes_display_move_to(RunesTerm *t, int row, int col)
runes_display_position_cursor(t, t->cr);
}
-/* XXX broken with utf8 */
void runes_display_show_string(RunesTerm *t, char *buf, size_t len)
{
if (len) {
int remaining = len, space_in_row = t->cols - t->col;
- buf[len] = '\0';
-
do {
int to_write = remaining > space_in_row ? space_in_row : remaining;
- char tmp;
runes_display_paint_rectangle(
t, t->cr, t->bgcolor, t->col, t->row, to_write, 1);
- tmp = buf[to_write];
- buf[to_write] = '\0';
- cairo_show_text(t->cr, buf);
- buf[to_write] = tmp;
+ pango_layout_set_text(t->layout, buf, to_write);
+ pango_cairo_update_layout(t->cr, t->layout);
+ pango_cairo_show_layout(t->cr, t->layout);
if (t->font_underline) {
double x, y;
@@ -141,10 +141,10 @@ void runes_display_show_string(RunesTerm *t, char *buf, size_t len)
cairo_get_current_point(t->cr, &x, &y);
cairo_save(t->cr);
cairo_set_line_width(t->cr, 1);
- cairo_move_to(t->cr, x, y - t->ascent + t->fonty - 0.5);
+ cairo_move_to(t->cr, x, y + t->fonty - 0.5);
cairo_line_to(
t->cr,
- x + (t->fontx * to_write), y - t->ascent + t->fonty - 0.5);
+ x + (t->fontx * to_write), y + t->fonty - 0.5);
cairo_stroke(t->cr);
cairo_restore(t->cr);
}
@@ -216,43 +216,37 @@ void runes_display_reset_text_attributes(RunesTerm *t)
void runes_display_set_bold(RunesTerm *t)
{
t->font_bold = 1;
- runes_display_recalculate_font(t);
- cairo_set_scaled_font(t->cr, t->font);
+ runes_display_recalculate_font_metrics(t);
}
void runes_display_reset_bold(RunesTerm *t)
{
t->font_bold = 0;
- runes_display_recalculate_font(t);
- cairo_set_scaled_font(t->cr, t->font);
+ runes_display_recalculate_font_metrics(t);
}
void runes_display_set_italic(RunesTerm *t)
{
t->font_italic = 1;
- runes_display_recalculate_font(t);
- cairo_set_scaled_font(t->cr, t->font);
+ runes_display_recalculate_font_metrics(t);
}
void runes_display_reset_italic(RunesTerm *t)
{
t->font_italic = 0;
- runes_display_recalculate_font(t);
- cairo_set_scaled_font(t->cr, t->font);
+ runes_display_recalculate_font_metrics(t);
}
void runes_display_set_underline(RunesTerm *t)
{
t->font_underline = 1;
- runes_display_recalculate_font(t);
- cairo_set_scaled_font(t->cr, t->font);
+ runes_display_recalculate_font_metrics(t);
}
void runes_display_reset_underline(RunesTerm *t)
{
t->font_underline = 0;
- runes_display_recalculate_font(t);
- cairo_set_scaled_font(t->cr, t->font);
+ runes_display_recalculate_font_metrics(t);
}
void runes_display_set_fg_color(RunesTerm *t, cairo_pattern_t *color)
@@ -386,24 +380,37 @@ void runes_display_cleanup(RunesTerm *t)
cairo_destroy(t->cr);
}
-static void runes_display_recalculate_font(RunesTerm *t)
+static void runes_display_recalculate_font_metrics(RunesTerm *t)
{
- cairo_font_extents_t extents;
+ PangoFontDescription *desc;
+ PangoContext *context;
+ PangoFontMetrics *metrics;
+
+ desc = pango_font_description_from_string(t->font_name);
- if (t->font) {
- cairo_scaled_font_destroy(t->font);
+ if (t->layout) {
+ context = pango_layout_get_context(t->layout);
+ }
+ else {
+ context = pango_font_map_create_context(
+ pango_cairo_font_map_get_default());
}
- t->font = runes_display_make_font(t);
- cairo_scaled_font_extents(t->font, &extents);
- t->fontx = extents.max_x_advance;
- t->fonty = extents.height;
- t->ascent = extents.ascent;
+ metrics = pango_context_get_metrics(context, desc, NULL);
+
+ t->fontx = pango_font_metrics_get_approximate_char_width(metrics) / PANGO_SCALE;
+ t->ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
+ t->fonty = t->ascent + pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
+
+ pango_font_description_free(desc);
+ if (!t->layout) {
+ g_object_unref(context);
+ }
}
static void runes_display_position_cursor(RunesTerm *t, cairo_t *cr)
{
- cairo_move_to(cr, t->col * t->fontx, t->row * t->fonty + t->ascent);
+ cairo_move_to(cr, t->col * t->fontx, t->row * t->fonty);
}
static void runes_display_paint_rectangle(
@@ -419,27 +426,6 @@ static void runes_display_paint_rectangle(
runes_display_position_cursor(t, t->cr);
}
-static cairo_scaled_font_t *runes_display_make_font(RunesTerm *t)
-{
- cairo_scaled_font_t *font;
- cairo_font_face_t *font_face;
- cairo_font_options_t *font_options;
- cairo_matrix_t font_matrix, ctm;
-
- font_face = cairo_toy_font_face_create(
- t->font_name,
- t->font_italic ? CAIRO_FONT_SLANT_ITALIC : CAIRO_FONT_SLANT_NORMAL,
- t->font_bold ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL);
- cairo_matrix_init_scale(&font_matrix, t->font_size, t->font_size);
- cairo_matrix_init_identity(&ctm);
- font_options = cairo_font_options_create();
- font = cairo_scaled_font_create(
- font_face, &font_matrix, &ctm, font_options);
- cairo_font_options_destroy(font_options);
- cairo_font_face_destroy(font_face);
- return font;
-}
-
static void runes_display_scroll_down(RunesTerm *t, int rows)
{
cairo_pattern_t *pattern;
diff --git a/runes.h b/runes.h
index 3291f7a..1fa77a7 100644
--- a/runes.h
+++ b/runes.h
@@ -2,6 +2,7 @@
#define _RUNES_H
#include <cairo.h>
+#include <pango/pangocairo.h>
#include <uv.h>
struct runes_term;
diff --git a/term.h b/term.h
index d8c2681..a9bd9c2 100644
--- a/term.h
+++ b/term.h
@@ -32,8 +32,7 @@ struct runes_term {
int ascent;
char *font_name;
- double font_size;
- cairo_scaled_font_t *font;
+ PangoLayout *layout;
char font_italic;
char font_bold;