diff --git a/COPYING b/COPYING index 49011f5..74f1aa8 100644 --- a/COPYING +++ b/COPYING @@ -87,3 +87,92 @@ The xkb input handling is based on the Xlib xkb handling: shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the XFree86 Project. + +The DejaVu fonts included in this package are from: + + Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. + Bitstream Vera is a trademark of Bitstream, Inc. + Permission is hereby granted, free of charge, to any person obtaining + a copy of the fonts accompanying this license ("Fonts") and associated + documentation files (the "Font Software"), to reproduce and distribute + the Font Software, including without limitation the rights to use, + copy, merge, publish, distribute, and/or sell copies of the Font + Software, and to permit persons to whom the Font Software is furnished + to do so, subject to the following conditions: + + The above copyright and trademark notices and this permission notice + shall be included in all copies of one or more of the Font Software + typefaces. + The Font Software may be modified, altered, or added to, and in + particular the designs of glyphs or characters in the Fonts may be + modified and additional glyphs or characters may be added to the Fonts, + only if the fonts are renamed to names not containing either the words + "Bitstream" or the word "Vera". + This License becomes null and void to the extent applicable to Fonts or + Font Software that has been modified and is distributed under the + "Bitstream Vera" names. + The Font Software may be sold as part of a larger software package but + no copy of one or more of the Font Software typefaces may be sold by + itself. + + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL + BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, + OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT + SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. + + Except as contained in this notice, the names of Gnome, the Gnome + Foundation, and Bitstream Inc., shall not be used in advertising or + otherwise to promote the sale, use or other dealings in this Font + Software without prior written authorization from the Gnome Foundation + or Bitstream Inc., respectively. For further information, + contact: fonts at gnome dot org. + + + Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of the fonts accompanying this license ("Fonts") and + associated documentation files (the "Font Software"), to reproduce + and distribute the modifications to the Bitstream Vera Font Software, + including without limitation the rights to use, copy, merge, publish, + distribute, and/or sell copies of the Font Software, and to permit + persons to whom the Font Software is furnished to do so, subject to + the following conditions: + + The above copyright and trademark notices and this permission notice + shall be included in all copies of one or more of the Font Software + typefaces. + + The Font Software may be modified, altered, or added to, and in + particular the designs of glyphs or characters in the Fonts may be + modified and additional glyphs or characters may be added to the + Fonts, only if the fonts are renamed to names not containing either + the words "Tavmjong Bah" or the word "Arev". + + This License becomes null and void to the extent applicable to Fonts + or Font Software that has been modified and is distributed under the + "Tavmjong Bah Arev" names. + + The Font Software may be sold as part of a larger software package but + no copy of one or more of the Font Software typefaces may be sold by + itself. + + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL + TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM + OTHER DEALINGS IN THE FONT SOFTWARE. + + Except as contained in this notice, the name of Tavmjong Bah shall not + be used in advertising or otherwise to promote the sale, use or other + dealings in this Font Software without prior written authorization + from Tavmjong Bah. For further information, contact: tavmjong@free.fr. diff --git a/Makefile.am b/Makefile.am index cdbb914..bf240dc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -40,6 +40,7 @@ libkmscon_core_la_SOURCES = \ src/console.c src/console.h \ src/output.c src/output.h \ src/output_context.c \ + src/output_math.c \ src/console_cell.c \ src/unicode.c src/unicode.h \ src/log.c src/log.h \ diff --git a/autogen.sh b/autogen.sh index b6547af..aa4cc76 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,4 +1,4 @@ #!/bin/sh mkdir -p m4/ autoreconf -i -./configure --enable-debug --enable-pango --enable-gles2 $* +./configure --enable-debug --enable-gles2 $* diff --git a/fonts/DejaVuSansMono.ttf b/fonts/DejaVuSansMono.ttf new file mode 100644 index 0000000..7260bd6 Binary files /dev/null and b/fonts/DejaVuSansMono.ttf differ diff --git a/src/console.c b/src/console.c index 4a010f1..58b3fce 100644 --- a/src/console.c +++ b/src/console.c @@ -36,8 +36,6 @@ #include #include -#include - #include "console.h" #include "font.h" #include "log.h" @@ -50,17 +48,11 @@ struct kmscon_console { struct kmscon_compositor *comp; struct kmscon_context *ctx; - /* GL texture and font */ - unsigned int tex; + /* font */ unsigned int res_x; unsigned int res_y; struct kmscon_font *font; - /* cairo surface */ - cairo_t *cr; - cairo_surface_t *surf; - unsigned char *surf_buf; - /* console cells */ struct kmscon_buffer *cells; unsigned int cells_x; @@ -71,69 +63,6 @@ struct kmscon_console { unsigned int cursor_y; }; -static void kmscon_console_free_res(struct kmscon_console *con) -{ - if (con && con->cr) { - kmscon_context_free_tex(con->ctx, con->tex); - cairo_destroy(con->cr); - cairo_surface_destroy(con->surf); - free(con->surf_buf); - con->tex = 0; - con->cr = NULL; - con->surf = NULL; - con->surf_buf = NULL; - } -} - -static int kmscon_console_new_res(struct kmscon_console *con) -{ - unsigned char *buf; - cairo_t *cr; - cairo_surface_t *surface; - int stride, ret; - cairo_format_t format = CAIRO_FORMAT_ARGB32; - - if (!con) - return -EINVAL; - - stride = cairo_format_stride_for_width(format, con->res_x); - - buf = malloc(stride * con->res_y); - if (!buf) - return -ENOMEM; - - surface = cairo_image_surface_create_for_data(buf, format, con->res_x, - con->res_y, stride); - if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) { - ret = -ENOMEM; - goto err_free; - } - - cr = cairo_create(surface); - if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) { - ret = -EFAULT; - goto err_cairo; - } - - kmscon_console_free_res(con); - - con->surf_buf = buf; - con->surf = surface; - con->cr = cr; - - con->tex = kmscon_context_new_tex(con->ctx); - - log_debug("console: new resolution %ux%u\n", con->res_x, con->res_y); - return 0; - -err_cairo: - cairo_destroy(cr); -err_free: - cairo_surface_destroy(surface); - free(buf); - return ret; -} - int kmscon_console_new(struct kmscon_console **out, struct kmscon_font_factory *ff, struct kmscon_compositor *comp) { @@ -192,7 +121,6 @@ void kmscon_console_unref(struct kmscon_console *con) if (--con->ref) return; - kmscon_console_free_res(con); kmscon_font_unref(con->font); kmscon_buffer_unref(con->cells); kmscon_compositor_unref(con->comp); @@ -280,48 +208,11 @@ int kmscon_console_resize(struct kmscon_console *con, unsigned int x, con->font = font; con->res_x = con->cells_x * kmscon_font_get_width(con->font); con->res_y = height; - - ret = kmscon_console_new_res(con); - if (ret) { - log_err("console: cannot create drawing buffers: %d\n", ret); - return ret; - } + log_debug("console: new resolution %ux%u\n", con->res_x, con->res_y); return 0; } -/* - * This redraws the console. It does not clip/copy the image onto any - * framebuffer. You must use kmscon_console_map() to do this. - * This allows to draw the console once and then map it onto multiple - * framebuffers so it is displayed on multiple monitors with different screen - * resolutions. - * You must have called kmscon_console_set_res() before. - */ -void kmscon_console_draw(struct kmscon_console *con) -{ - if (!con || !con->cr) - return; - - cairo_save(con->cr); - - cairo_set_operator(con->cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(con->cr, 0.0, 0.0, 0.0, 0.0); - cairo_paint(con->cr); - - cairo_set_operator(con->cr, CAIRO_OPERATOR_OVER); - cairo_set_source_rgba(con->cr, 1.0, 1.0, 1.0, 1.0); - - kmscon_buffer_draw(con->cells, con->font, con->cr, con->res_x, - con->res_y); - - cairo_restore(con->cr); - - /* refresh GL texture contents */ - kmscon_context_set_tex(con->ctx, con->tex, con->res_x, con->res_y, - con->surf_buf); -} - /* * This maps the console onto the current GL framebuffer. It expects the * framebuffer to have 0/0 in the middle, -1/-1 in the upper left and 1/1 in the @@ -334,15 +225,10 @@ void kmscon_console_draw(struct kmscon_console *con) */ void kmscon_console_map(struct kmscon_console *con) { - static const float vertices[] = { -1, -1, 1, -1, -1, 1, - 1, -1, 1, 1, -1, 1 }; - static const float texpos[] = { 0, 0, 1, 0, 0, 1, - 1, 0, 1, 1, 0, 1 }; - - if (!con || !con->cr) + if (!con) return; - kmscon_context_draw_tex(con->ctx, vertices, texpos, 6, con->tex); + kmscon_buffer_draw(con->cells, con->font); } void kmscon_console_write(struct kmscon_console *con, kmscon_symbol_t ch) diff --git a/src/console.h b/src/console.h index 0b5373e..55fde58 100644 --- a/src/console.h +++ b/src/console.h @@ -53,8 +53,7 @@ void kmscon_buffer_unref(struct kmscon_buffer *buf); int kmscon_buffer_resize(struct kmscon_buffer *buf, unsigned int x, unsigned int y); -void kmscon_buffer_draw(struct kmscon_buffer *buf, struct kmscon_font *font, - void *dcr, unsigned int width, unsigned int height); +void kmscon_buffer_draw(struct kmscon_buffer *buf, struct kmscon_font *font); unsigned int kmscon_buffer_get_width(struct kmscon_buffer *buf); unsigned int kmscon_buffer_get_height(struct kmscon_buffer *buf); @@ -76,7 +75,6 @@ unsigned int kmscon_console_get_height(struct kmscon_console *con); int kmscon_console_resize(struct kmscon_console *con, unsigned int x, unsigned int y, unsigned int height); -void kmscon_console_draw(struct kmscon_console *con); void kmscon_console_map(struct kmscon_console *con); void kmscon_console_write(struct kmscon_console *con, kmscon_symbol_t ch); diff --git a/src/console_cell.c b/src/console_cell.c index e3608e0..3a8ce4a 100644 --- a/src/console_cell.c +++ b/src/console_cell.c @@ -80,8 +80,6 @@ #include #include -#include - #include "console.h" #include "log.h" #include "unicode.h" @@ -116,6 +114,8 @@ struct kmscon_buffer { unsigned int size_y; unsigned int fill; struct line **current; + + struct kmscon_m4_stack *stack; }; static void destroy_cell(struct cell *cell) @@ -216,13 +216,19 @@ int kmscon_buffer_new(struct kmscon_buffer **out, unsigned int x, log_debug("console: new buffer object\n"); - ret = kmscon_buffer_resize(buf, x, y); + ret = kmscon_m4_stack_new(&buf->stack); if (ret) goto err_free; + ret = kmscon_buffer_resize(buf, x, y); + if (ret) + goto err_stack; + *out = buf; return 0; +err_stack: + kmscon_m4_stack_free(buf->stack); err_free: free(buf); return ret; @@ -257,6 +263,7 @@ void kmscon_buffer_unref(struct kmscon_buffer *buf) free_line(buf->current[i]); free(buf->current); + kmscon_m4_stack_free(buf->stack); free(buf); log_debug("console: destroying buffer object\n"); } @@ -415,32 +422,30 @@ int kmscon_buffer_resize(struct kmscon_buffer *buf, unsigned int x, return 0; } -void kmscon_buffer_draw(struct kmscon_buffer *buf, struct kmscon_font *font, - void *dcr, unsigned int width, unsigned int height) +void kmscon_buffer_draw(struct kmscon_buffer *buf, struct kmscon_font *font) { - cairo_t *cr; - double xs, ys, cx, cy; + float xs, ys; unsigned int i, j, k, num; struct line *iter, *line; struct cell *cell; + float *m; - if (!buf || !font || !dcr) + if (!buf || !font) return; - cr = dcr; - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); + m = kmscon_m4_stack_tip(buf->stack); + kmscon_m4_identity(m); - xs = width / (double)buf->size_x; - ys = height / (double)buf->size_y; + xs = 1.0 / buf->size_x; + ys = 1.0 / buf->size_y; + kmscon_m4_scale(m, 2, 2, 1); + kmscon_m4_trans(m, -0.5, -0.5, 0); + kmscon_m4_scale(m, xs, ys, 1); iter = buf->position; k = 0; - cy = 0; for (i = 0; i < buf->size_y; ++i) { - cx = 0; - if (iter) { line = iter; iter = iter->next; @@ -460,11 +465,16 @@ void kmscon_buffer_draw(struct kmscon_buffer *buf, struct kmscon_font *font, for (j = 0; j < num; ++j) { cell = &line->cells[j]; - kmscon_font_draw(font, cell->ch, cr, cx, cy); - cx += xs; - } + m = kmscon_m4_stack_push(buf->stack); + if (!m) { + log_warning("console: cannot push matrix\n"); + break; + } - cy += ys; + kmscon_m4_trans(m, j, i, 0); + kmscon_font_draw(font, cell->ch, m); + m = kmscon_m4_stack_pop(buf->stack); + } } } diff --git a/src/font.h b/src/font.h index 8d1ee55..4f2a336 100644 --- a/src/font.h +++ b/src/font.h @@ -54,7 +54,6 @@ void kmscon_font_unref(struct kmscon_font *font); unsigned int kmscon_font_get_height(struct kmscon_font *font); unsigned int kmscon_font_get_width(struct kmscon_font *font); -int kmscon_font_draw(struct kmscon_font *font, kmscon_symbol_t ch, - void *dcr, uint32_t x, uint32_t y); +int kmscon_font_draw(struct kmscon_font *font, kmscon_symbol_t ch, float *m); #endif /* KMSCON_FONT_H */ diff --git a/src/font_freetype.c b/src/font_freetype.c index ccb59e5..8a1e55f 100644 --- a/src/font_freetype.c +++ b/src/font_freetype.c @@ -32,9 +32,11 @@ */ #include +#include #include #include +#include #include "font.h" #include "log.h" #include "output.h" @@ -58,12 +60,115 @@ struct kmscon_font { FT_Face face; unsigned int width; unsigned int height; + GHashTable *glyphs; }; struct kmscon_glyph { - unsigned long ref; + struct kmscon_context *ctx; + bool valid; + unsigned int tex; + unsigned int width; + unsigned int height; + int left; + int top; + unsigned int advance; }; +static int kmscon_glyph_new(struct kmscon_glyph **out, kmscon_symbol_t key, + struct kmscon_font *font) +{ + struct kmscon_glyph *glyph; + FT_Error err; + FT_UInt idx; + FT_Bitmap *bmap; + int ret; + const uint32_t *val; + size_t len; + unsigned char *data, d; + unsigned int i, j; + + if (!out) + return -EINVAL; + + glyph = malloc(sizeof(*glyph)); + if (!glyph) + return -ENOMEM; + + memset(glyph, 0, sizeof(*glyph)); + glyph->ctx = font->ff->ctx; + + val = kmscon_symbol_get(font->ff->st, &key, &len); + + if (!val[0]) + goto ready; + + /* TODO: Add support for combining characters */ + idx = FT_Get_Char_Index(font->face, val[0]); + err = FT_Load_Glyph(font->face, idx, FT_LOAD_DEFAULT); + if (err) { + ret = -EFAULT; + goto err_free; + } + + err = FT_Render_Glyph(font->face->glyph, FT_RENDER_MODE_NORMAL); + if (err) { + ret = -EFAULT; + goto err_free; + } + + bmap = &font->face->glyph->bitmap; + if (!bmap->width || !bmap->rows) + goto ready; + + glyph->tex = kmscon_context_new_tex(glyph->ctx); + data = malloc(sizeof(unsigned char) * bmap->width * bmap->rows * 4); + if (!data) { + ret = -ENOMEM; + goto err_tex; + } + + for (j = 0; j < bmap->rows; ++j) { + for (i = 0; i < bmap->width; ++i) { + d = bmap->buffer[i + bmap->width * j]; + data[4 * (i + j * bmap->width)] = d; + data[4 * (i + j * bmap->width) + 1] = d; + data[4 * (i + j * bmap->width) + 2] = d; + data[4 * (i + j * bmap->width) + 3] = d; + } + } + + kmscon_context_set_tex(glyph->ctx, glyph->tex, bmap->width, + bmap->rows, data); + free(data); + + glyph->width = bmap->width; + glyph->height = bmap->rows; + glyph->left = font->face->glyph->bitmap_left; + glyph->top = font->face->glyph->bitmap_top; + glyph->advance = font->face->glyph->advance.x >> 6; + glyph->valid = true; + +ready: + *out = glyph; + return 0; + +err_tex: + kmscon_context_free_tex(glyph->ctx, glyph->tex); +err_free: + free(glyph); + return ret; +} + +static void kmscon_glyph_destroy(struct kmscon_glyph *glyph) +{ + if (!glyph) + return; + + if (glyph->valid) + kmscon_context_free_tex(glyph->ctx, glyph->tex); + free(glyph); +} + int kmscon_font_factory_new(struct kmscon_font_factory **out, struct kmscon_symbol_table *st, struct kmscon_compositor *comp) { @@ -137,9 +242,12 @@ int kmscon_font_factory_load(struct kmscon_font_factory *ff, const char *estr = "unknown error"; int ret; - if (!ff || !out) + if (!ff || !out || !height) return -EINVAL; + if (!width) + width = height; + font = malloc(sizeof(*font)); if (!font) return -ENOMEM; @@ -149,7 +257,8 @@ int kmscon_font_factory_load(struct kmscon_font_factory *ff, font->width = width; font->height = height; - err = FT_New_Face(ff->lib, "/usr/share/fonts/TTF/DejaVuSansMono.ttf", + /* TODO: Use fontconfig to get font paths */ + err = FT_New_Face(ff->lib, "./fonts/DejaVuSansMono.ttf", 0, &font->face); if (err) { if (err == FT_Err_Unknown_File_Format) @@ -173,6 +282,13 @@ int kmscon_font_factory_load(struct kmscon_font_factory *ff, goto err_face; } + font->glyphs = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) kmscon_glyph_destroy); + if (!font->glyphs) { + ret = -ENOMEM; + goto err_face; + } + kmscon_font_factory_ref(ff); font->ff = ff; *out = font; @@ -202,6 +318,7 @@ void kmscon_font_unref(struct kmscon_font *font) if (--font->ref) return; + g_hash_table_unref(font->glyphs); FT_Done_Face(font->face); kmscon_font_factory_unref(font->ff); free(font); @@ -223,13 +340,49 @@ unsigned int kmscon_font_get_width(struct kmscon_font *font) return font->width; } -int kmscon_font_draw(struct kmscon_font *font, kmscon_symbol_t ch, - void *dcr, uint32_t x, uint32_t y) +static int kmscon_font_lookup(struct kmscon_font *font, + kmscon_symbol_t key, struct kmscon_glyph **out) { + struct kmscon_glyph *glyph; + int ret; + + if (!font || !out) + return -EINVAL; + + glyph = g_hash_table_lookup(font->glyphs, GUINT_TO_POINTER(key)); + if (!glyph) { + ret = kmscon_glyph_new(&glyph, key, font); + if (ret) + return ret; + + g_hash_table_insert(font->glyphs, GUINT_TO_POINTER(key), glyph); + } + + *out = glyph; + return 0; +} + +int kmscon_font_draw(struct kmscon_font *font, kmscon_symbol_t ch, float *m) +{ + int ret; + struct kmscon_glyph *glyph; + static const float val[] = { 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1 }; + if (!font) return -EINVAL; - /* still TODO */ + ret = kmscon_font_lookup(font, ch, &glyph); + if (ret) + return ret; + + if (!glyph->valid) + return 0; + + kmscon_m4_scale(m, 1.0 / glyph->advance, 1.0 / font->height, 1); + kmscon_m4_trans(m, glyph->left, font->height - glyph->top, 0); + kmscon_m4_scale(m, glyph->width, glyph->height, 1); + + kmscon_context_draw_tex(font->ff->ctx, val, val, 6, glyph->tex, m); return 0; } diff --git a/src/font_pango.c b/src/font_pango.c index 22c58ee..af546cc 100644 --- a/src/font_pango.c +++ b/src/font_pango.c @@ -44,488 +44,9 @@ #include "output.h" #include "unicode.h" -enum glyph_type { - GLYPH_NONE, - GLYPH_LAYOUT, - GLYPH_STR, -}; - -struct kmscon_glyph { - size_t ref; - kmscon_symbol_t ch; - unsigned int width; - - int type; - - union { - struct layout { - PangoLayout *layout; - } layout; - struct str { - PangoFont *font; - PangoGlyphString *str; - uint32_t ascent; - } str; - } src; -}; - -struct kmscon_font_factory { - unsigned long ref; - struct kmscon_symbol_table *st; - struct kmscon_compositor *comp; - struct kmscon_context *ctx; -}; - -struct kmscon_font { - size_t ref; - struct kmscon_symbol_table *st; - - unsigned int width; - unsigned int height; - GHashTable *glyphs; - PangoContext *ctx; -}; - -static int kmscon_font_lookup(struct kmscon_font *font, - kmscon_symbol_t key, struct kmscon_glyph **out); - /* - * Glyphs - * Glyphs are for internal use only! The outside world uses kmscon_char - * objects in combination with kmscon_font to draw characters. Internally, we - * cache a kmscon_glyph for every character that is drawn. - * This allows us to speed up the drawing operations because most characters are - * already cached. - * - * Glyphs are cached in a hash-table by each font. If a character is drawn, we - * look it up in the hash-table (or create a new one if none is found) and draw - * it to the framebuffer. - * A glyph may use several ways to cache the glyph description: - * GLYPH_NONE: - * No information is currently attached so the glyph cannot be drawn. - * GLYPH_LAYOUT: - * The most basic drawing operation. This is the slowest of all but can draw - * any text you want. It uses a PangoLayout internally and recalculates the - * character sizes each time we draw them. - */ -static int kmscon_glyph_new(struct kmscon_glyph **out, kmscon_symbol_t ch) -{ - struct kmscon_glyph *glyph; - - if (!out) - return -EINVAL; - - glyph = malloc(sizeof(*glyph)); - if (!glyph) - return -ENOMEM; - - memset(glyph, 0, sizeof(*glyph)); - glyph->ref = 1; - glyph->type = GLYPH_NONE; - glyph->ch = ch; - - *out = glyph; - return 0; -} - -/* - * Reset internal glyph description. You must use kmscon_glyph_set() again to - * attach new glyph descriptions. - */ -static void kmscon_glyph_reset(struct kmscon_glyph *glyph) -{ - if (!glyph) - return; - - switch (glyph->type) { - case GLYPH_LAYOUT: - g_object_unref(glyph->src.layout.layout); - break; - case GLYPH_STR: - g_object_unref(glyph->src.str.font); - pango_glyph_string_free(glyph->src.str.str); - break; - } - - glyph->type = GLYPH_NONE; - glyph->width = 0; -} - -static void kmscon_glyph_ref(struct kmscon_glyph *glyph) -{ - if (!glyph) - return; - - ++glyph->ref; -} - -static void kmscon_glyph_unref(struct kmscon_glyph *glyph) -{ - if (!glyph || !glyph->ref) - return; - - if (--glyph->ref) - return; - - kmscon_glyph_reset(glyph); - free(glyph); -} - -/* - * Generate glyph description. - * This connects the glyph with the given font an generates the fastest glyph - * description. - * Returns 0 on success. - */ -static int kmscon_glyph_set(struct kmscon_glyph *glyph, - struct kmscon_font *font) -{ - PangoLayout *layout; - PangoLayoutLine *line; - PangoGlyphItem *tmp; - PangoGlyphString *str; - PangoRectangle rec; - size_t len; - const char *val; - - if (!glyph || !font) - return -EINVAL; - - layout = pango_layout_new(font->ctx); - if (!layout) - return -EINVAL; - - val = kmscon_symbol_get_u8(font->st, glyph->ch, &len); - pango_layout_set_text(layout, val, len); - kmscon_symbol_free_u8(val); - - pango_layout_get_extents(layout, NULL, &rec); - line = pango_layout_get_line_readonly(layout, 0); - - if (!line || !line->runs || line->runs->next) { - kmscon_glyph_reset(glyph); - glyph->type = GLYPH_LAYOUT; - glyph->src.layout.layout = layout; - } else { - tmp = line->runs->data; - str = pango_glyph_string_copy(tmp->glyphs); - if (!str) { - g_object_unref(layout); - return -ENOMEM; - } - - kmscon_glyph_reset(glyph); - glyph->type = GLYPH_STR; - - glyph->src.str.str = str; - glyph->src.str.font = - g_object_ref(tmp->item->analysis.font); - glyph->src.str.ascent = - PANGO_PIXELS_CEIL(pango_layout_get_baseline(layout)); - - g_object_unref(layout); - } - - glyph->width = PANGO_PIXELS(rec.width); - return 0; -} - -int kmscon_font_factory_new(struct kmscon_font_factory **out, - struct kmscon_symbol_table *st, struct kmscon_compositor *comp) -{ - struct kmscon_font_factory *ff; - - if (!out || !st || !comp) - return -EINVAL; - - ff = malloc(sizeof(*ff)); - if (!ff) - return -ENOMEM; - - memset(ff, 0, sizeof(*ff)); - ff->ref = 1; - ff->st = st; - ff->comp = comp; - ff->ctx = kmscon_compositor_get_context(comp); - - kmscon_compositor_ref(ff->comp); - kmscon_symbol_table_ref(ff->st); - *out = ff; - - return 0; -} - -void kmscon_font_factory_ref(struct kmscon_font_factory *ff) -{ - if (!ff) - return; - - ++ff->ref; -} - -void kmscon_font_factory_unref(struct kmscon_font_factory *ff) -{ - if (!ff || !ff->ref) - return; - - if (--ff->ref) - return; - - kmscon_compositor_unref(ff->comp); - kmscon_symbol_table_unref(ff->st); - free(ff); -} - -/* - * Measure font width - * We simply draw all ASCII characters and use the average width as default - * character width. - * This has the side effect that all ASCII characters are already cached and the - * console will speed up. - */ -static int measure_width(struct kmscon_font *font) -{ - unsigned int i, num, width; - int ret; - kmscon_symbol_t ch; - struct kmscon_glyph *glyph; - - if (!font) - return -EINVAL; - - width = 0; - num = 0; - for (i = 0; i < 127; ++i) { - ch = kmscon_symbol_make(i); - - ret = kmscon_font_lookup(font, ch, &glyph); - if (ret) - continue; - - if (glyph->width > 0) { - width += glyph->width; - num++; - } - - kmscon_glyph_unref(glyph); - } - - if (!num) - return -EFAULT; - - font->width = width / num; - log_debug("font: width is %u\n", font->width); - - return 0; -} - -/* - * Creates a new font - * \height is the height in pixel that we have for each character. - * Returns 0 on success and stores the new font in \out. + * This backend is currently no longer available. See git-history for old pango + * backends. Use FreeType instead. */ -int kmscon_font_factory_load(struct kmscon_font_factory *ff, - struct kmscon_font **out, unsigned int width, unsigned int height) -{ - struct kmscon_font *font; - int ret; - PangoFontDescription *desc; - PangoFontMap *map; - PangoLanguage *lang; - cairo_font_options_t *opt; - - if (!ff || !out || !height) - return -EINVAL; - - log_debug("font: new font (height %u)\n", height); - - font = malloc(sizeof(*font)); - if (!font) - return -ENOMEM; - font->ref = 1; - font->height = height; - font->st = ff->st; - - map = pango_cairo_font_map_get_default(); - if (!map) { - ret = -EFAULT; - goto err_free; - } - - font->ctx = pango_font_map_create_context(map); - if (!font->ctx) { - ret = -EFAULT; - goto err_free; - } - - pango_context_set_base_dir(font->ctx, PANGO_DIRECTION_LTR); - - desc = pango_font_description_from_string("monospace"); - if (!desc) { - ret = -EFAULT; - goto err_ctx; - } - - pango_font_description_set_absolute_size(desc, PANGO_SCALE * height); - pango_context_set_font_description(font->ctx, desc); - pango_font_description_free(desc); - - lang = pango_language_get_default(); - if (!lang) { - ret = -EFAULT; - goto err_ctx; - } - - pango_context_set_language(font->ctx, lang); - - if (!pango_cairo_context_get_font_options(font->ctx)) { - opt = cairo_font_options_create(); - if (!opt) { - ret = -EFAULT; - goto err_ctx; - } - - pango_cairo_context_set_font_options(font->ctx, opt); - cairo_font_options_destroy(opt); - } - - font->glyphs = g_hash_table_new_full(g_direct_hash, g_direct_equal, - NULL, (GDestroyNotify) kmscon_glyph_unref); - if (!font->glyphs) { - ret = -ENOMEM; - goto err_ctx; - } - - ret = measure_width(font); - if (ret) - goto err_hash; - - kmscon_symbol_table_ref(font->st); - *out = font; - - return 0; - -err_hash: - g_hash_table_unref(font->glyphs); -err_ctx: - g_object_unref(font->ctx); -err_free: - free(font); - return ret; -} - -void kmscon_font_ref(struct kmscon_font *font) -{ - if (!font) - return; - - ++font->ref; -} - -void kmscon_font_unref(struct kmscon_font *font) -{ - if (!font || !font->ref) - return; - - if (--font->ref) - return; - - g_hash_table_unref(font->glyphs); - g_object_unref(font->ctx); - kmscon_symbol_table_unref(font->st); - free(font); - log_debug("font: destroying font\n"); -} - -unsigned int kmscon_font_get_width(struct kmscon_font *font) -{ - if (!font) - return 0; - - return font->width; -} - -unsigned int kmscon_font_get_height(struct kmscon_font *font) -{ - if (!font) - return 0; - - return font->height; -} - -/* - * Get glyph for given key. If no glyph can be found in the hash-table, then a - * new glyph is created and added to the hash-table. - * Returns 0 on success and stores the glyph with a new reference in \out. - */ -static int kmscon_font_lookup(struct kmscon_font *font, - kmscon_symbol_t key, struct kmscon_glyph **out) -{ - struct kmscon_glyph *glyph; - int ret; - - if (!font || !out) - return -EINVAL; - - glyph = g_hash_table_lookup(font->glyphs, GUINT_TO_POINTER(key)); - if (!glyph) { - ret = kmscon_glyph_new(&glyph, key); - if (ret) - return ret; - - ret = kmscon_glyph_set(glyph, font); - if (ret) - goto err_glyph; - - g_hash_table_insert(font->glyphs, GUINT_TO_POINTER(key), glyph); - } - - kmscon_glyph_ref(glyph); - *out = glyph; - return 0; - -err_glyph: - kmscon_glyph_unref(glyph); - return ret; -} - -/* - * This draws a glyph for characters \ch into the given cairo context \cr. - * The glyph will be drawn with the upper-left corner at x/y. - * Returns 0 on success. - */ -int kmscon_font_draw(struct kmscon_font *font, kmscon_symbol_t ch, void *dcr, - uint32_t x, uint32_t y) -{ - struct kmscon_glyph *glyph; - int ret; - cairo_t *cr = dcr; - - if (!font || !ch || !cr) - return -EINVAL; - - ret = kmscon_font_lookup(font, ch, &glyph); - if (ret) - return ret; - - switch (glyph->type) { - case GLYPH_LAYOUT: - cairo_move_to(cr, x, y); - pango_cairo_update_layout(cr, glyph->src.layout.layout); - pango_cairo_show_layout(cr, glyph->src.layout.layout); - break; - case GLYPH_STR: - cairo_move_to(cr, x, y + glyph->src.str.ascent); - pango_cairo_show_glyph_string(cr, glyph->src.str.font, - glyph->src.str.str); - break; - default: - ret = -EFAULT; - break; - } - - kmscon_glyph_unref(glyph); - - return 0; -} +#error "Pango backend is currently not supported" diff --git a/src/output.h b/src/output.h index 31985dd..44f9169 100644 --- a/src/output.h +++ b/src/output.h @@ -140,7 +140,7 @@ void kmscon_context_clear(struct kmscon_context *ctx); void kmscon_context_draw_def(struct kmscon_context *ctx, float *vertices, float *colors, size_t num); void kmscon_context_draw_tex(struct kmscon_context *ctx, const float *vertices, - const float *texcoords, size_t num, unsigned int tex); + const float *texcoords, size_t num, unsigned int tex, const float *m); unsigned int kmscon_context_new_tex(struct kmscon_context *ctx); void kmscon_context_free_tex(struct kmscon_context *ctx, unsigned int tex); void kmscon_context_set_tex(struct kmscon_context *ctx, unsigned int tex, diff --git a/src/output_context.c b/src/output_context.c index 66de529..0e3d1e9 100644 --- a/src/output_context.c +++ b/src/output_context.c @@ -183,7 +183,15 @@ static void clear_gl_error() /* return true if there is a pending GL error */ static bool has_gl_error() { - return glGetError() != GL_NO_ERROR; + GLenum err; + + err = glGetError(); + if (err != GL_NO_ERROR) { + log_err("context: GL error %d\n", err); + return true; + } + + return false; } /* external shader sources; generated during build */ @@ -643,21 +651,19 @@ void kmscon_context_draw_def(struct kmscon_context *ctx, float *vertices, } void kmscon_context_draw_tex(struct kmscon_context *ctx, const float *vertices, - const float *texcoords, size_t num, unsigned int tex) + const float *texcoords, size_t num, unsigned int tex, const float *m) { - static const float m[16] = { 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 }; + float mat[16]; if (!ctx) return; + kmscon_m4_transp_dest(mat, m); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex); ctx->proc_use_program(ctx->tex_program); - ctx->proc_uniform_matrix_4fv(ctx->tex_uni_projection, 1, GL_FALSE, m); + ctx->proc_uniform_matrix_4fv(ctx->tex_uni_projection, 1, GL_FALSE, mat); ctx->proc_uniform_1i(ctx->tex_uni_texture, 0); ctx->proc_vertex_attrib_pointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices); diff --git a/src/terminal.c b/src/terminal.c index b95b8eb..616cb3a 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -71,7 +71,6 @@ static void draw_all(struct kmscon_idle *idle, void *data) ctx = kmscon_compositor_get_context(term->comp); kmscon_eloop_rm_idle(idle); - kmscon_console_draw(term->console); iter = term->outputs; for (; iter; iter = iter->next) { diff --git a/tests/test_console.c b/tests/test_console.c index 536a50b..f150f96 100644 --- a/tests/test_console.c +++ b/tests/test_console.c @@ -118,7 +118,6 @@ static void map_outputs(struct console *con) if (kmscon_compositor_is_asleep(con->comp)) return; - kmscon_console_draw(con->con); ctx = kmscon_compositor_get_context(con->comp); iter = kmscon_compositor_get_outputs(con->comp);