diff --git a/repos/demo/include/scout/canvas.h b/repos/demo/include/scout/canvas.h index d4f3451bc6..695142781c 100644 --- a/repos/demo/include/scout/canvas.h +++ b/repos/demo/include/scout/canvas.h @@ -102,7 +102,7 @@ class Scout::Canvas : public Canvas_base { char buf[len + 1]; Genode::strncpy(buf, str, len + 1); - Text_painter::paint(_surface, Point(x, y), *font, color, buf); + Text_painter::paint(_surface, Text_painter::Position(x, y), *font, color, buf); } void draw_box(int x, int y, int w, int h, Color c) diff --git a/repos/demo/src/app/launchpad/loadbar.h b/repos/demo/src/app/launchpad/loadbar.h index 6e09eb301f..978b70dc3a 100644 --- a/repos/demo/src/app/launchpad/loadbar.h +++ b/repos/demo/src/app/launchpad/loadbar.h @@ -168,8 +168,8 @@ class Loadbar : public Scout::Parent_element { if (!_font) return; _txt = txt; - _txt_w = _font->str_w(_txt, Scout::strlen(_txt)); - _txt_h = _font->str_h(_txt, Scout::strlen(_txt)); + _txt_w = _font->string_width(_txt, Scout::strlen(_txt)).decimal(); + _txt_h = _font->bounding_box().h(); _txt_len = Scout::strlen(_txt); } diff --git a/repos/demo/src/app/launchpad/section.h b/repos/demo/src/app/launchpad/section.h index d18439102f..b5726b5ce8 100644 --- a/repos/demo/src/app/launchpad/section.h +++ b/repos/demo/src/app/launchpad/section.h @@ -36,8 +36,8 @@ class Section : public Scout::Parent_element char const *_txt; Scout::Font *_font; - int _txt_w = _font->str_w(_txt, Scout::strlen(_txt)); - int _txt_h = _font->str_h(_txt, Scout::strlen(_txt)); + int _txt_w = _font->string_width(_txt, Scout::strlen(_txt)).decimal(); + int _txt_h = _font->bounding_box().h(); int _txt_len = Scout::strlen(_txt); int _r_add; diff --git a/repos/demo/src/app/scout/elements.cc b/repos/demo/src/app/scout/elements.cc index b8b04ef377..b5c8cb7fe1 100644 --- a/repos/demo/src/app/scout/elements.cc +++ b/repos/demo/src/app/scout/elements.cc @@ -232,8 +232,10 @@ Token::Token(Style *style, const char *str, int len) _flags.takes_focus = 0; if (!_style) return; - _min_size = Area(_style->font->str_w(str, len) + _style->font->str_w(" ", 1), - _style->font->str_h(str, len)); + + _min_size = Area(_style->font->string_width(str, len).decimal() + + _style->font->string_width(" ").decimal(), + _style->font->bounding_box().h()); } diff --git a/repos/demo/src/app/scout/styles.h b/repos/demo/src/app/scout/styles.h index f48dcb178b..4b5240c61a 100644 --- a/repos/demo/src/app/scout/styles.h +++ b/repos/demo/src/app/scout/styles.h @@ -14,6 +14,10 @@ #ifndef _STYLES_H_ #define _STYLES_H_ +/* Genode includes */ +#include + +/* local includes */ #include "elements.h" extern char _binary_mono16_tff_start[]; @@ -26,29 +30,33 @@ extern char _binary_vera24_tff_start[]; namespace Scout { - static Font label_font (&_binary_verabi10_tff_start[0]); - static Font default_font (&_binary_vera16_tff_start[0]); - static Font italic_font (&_binary_verai16_tff_start[0]); - static Font mono_font (&_binary_mono16_tff_start[0]); - static Font chapter_font (&_binary_vera24_tff_start[0]); - static Font section_font (&_binary_vera20_tff_start[0]); - static Font subsection_font (&_binary_vera18_tff_start[0]); - - static Color default_color (0, 0, 0); - static Color text_color (20, 20, 20); - static Color verbatim_bgcol (0, 0, 0, 26); - - static Style plain_style (&default_font, text_color, 0); - static Style bold_style (&default_font, text_color, Style::ATTR_BOLD); - static Style mono_style (&mono_font, text_color, 0); - static Style italic_style (&italic_font, text_color, 0); - - static Style link_style (&default_font, Color(0, 0, 255), 0); - - static Style chapter_style (&chapter_font, default_color, 0); - static Style section_style (§ion_font, default_color, 0); - static Style subsection_style (&subsection_font, default_color, 0); - static Style navbar_style (&default_font, Color(0, 0, 0, 127), 0); + static Tff_font::Static_glyph_buffer<4096> _glyph_buffer { }; + + static Tff_font label_font { &_binary_verabi10_tff_start, _glyph_buffer }; + static Tff_font default_font { &_binary_vera16_tff_start, _glyph_buffer }; + static Tff_font italic_font { &_binary_verai16_tff_start, _glyph_buffer }; + static Tff_font mono_font { &_binary_mono16_tff_start, _glyph_buffer }; + static Tff_font chapter_font { &_binary_vera24_tff_start, _glyph_buffer }; + static Tff_font section_font { &_binary_vera20_tff_start, _glyph_buffer }; + static Tff_font subsection_font { &_binary_vera18_tff_start, _glyph_buffer }; + + static Tff_font &title_font = subsection_font; + + static Color default_color { 0, 0, 0 }; + static Color text_color { 20, 20, 20 }; + static Color verbatim_bgcol { 0, 0, 0, 26 }; + + static Style plain_style { &default_font, text_color, 0 }; + static Style bold_style { &default_font, text_color, Style::ATTR_BOLD }; + static Style mono_style { &mono_font, text_color, 0 }; + static Style italic_style { &italic_font, text_color, 0 }; + + static Style link_style { &default_font, Color(0, 0, 255), 0 }; + + static Style chapter_style { &chapter_font, default_color, 0 }; + static Style section_style { §ion_font, default_color, 0 }; + static Style subsection_style { &subsection_font, default_color, 0 }; + static Style navbar_style { &default_font, Color(0, 0, 0, 127), 0 }; } #endif /* _STYLES_H_ */ diff --git a/repos/demo/src/app/scout/titlebar.h b/repos/demo/src/app/scout/titlebar.h index 1c2d74f5b1..bf5c4321df 100644 --- a/repos/demo/src/app/scout/titlebar.h +++ b/repos/demo/src/app/scout/titlebar.h @@ -15,15 +15,11 @@ #define _TITLEBAR_H_ #include "widgets.h" - -#define TITLE_TFF _binary_vera18_tff_start -extern char TITLE_TFF[]; +#include "styles.h" namespace Scout { template class Titlebar; } -static Scout::Font title_font(TITLE_TFF); - template class Scout::Titlebar : public Parent_element { @@ -47,8 +43,8 @@ class Scout::Titlebar : public Parent_element void text(const char *txt) { _txt = txt ? txt : "Scout"; - _txt_w = title_font.str_w(_txt, strlen(_txt)); - _txt_h = title_font.str_h(_txt, strlen(_txt)); + _txt_w = title_font.string_width(_txt, strlen(_txt)).decimal(); + _txt_h = title_font.bounding_box().h(); _txt_len = strlen(_txt); } diff --git a/repos/demo/src/server/nitlog/main.cc b/repos/demo/src/server/nitlog/main.cc index 237786bbe6..cf18de13d7 100644 --- a/repos/demo/src/server/nitlog/main.cc +++ b/repos/demo/src/server/nitlog/main.cc @@ -26,8 +26,8 @@ /* * Nitpicker's graphics backend */ -#include #include +#include enum { LOG_W = 80 }; /* number of visible characters per line */ @@ -41,10 +41,9 @@ typedef Genode::Color Color; /* - * Font initialization + * Builtin font */ -extern char _binary_mono_tff_start; -Font default_font(&_binary_mono_tff_start); +extern char _binary_mono_tff_start[]; namespace Nitlog { @@ -89,7 +88,8 @@ class Canvas : public Canvas_base void draw_string(Point p, Font const &font, Color color, char const *sstr) { - Text_painter::paint(_surface, p, font, color, sstr); + Text_painter::paint(_surface, Text_painter::Position(p.x(), p.y()), + font, color, sstr); } void draw_box(Rect rect, Color color) @@ -145,7 +145,7 @@ class Log_entry * marks a transition of output from one session to another. This * information is used to separate sessions visually. */ - void draw(Canvas_base &canvas, int y, int new_section = false) + void draw(Canvas_base &canvas, Font const &font, int y, int new_section = false) { Color label_fgcol = Color(Genode::min(255, _color.r + 200), Genode::min(255, _color.g + 200), @@ -155,12 +155,12 @@ class Log_entry Color text_bgcol = Color(_color.r / 2, _color.g / 2, _color.b / 2); /* calculate label dimensions */ - int label_w = default_font.str_w(_label); - int label_h = default_font.str_h(_label); + int label_w = font.string_width(_label).decimal(); + int label_h = font.bounding_box().h(); if (new_section) { canvas.draw_box(Rect(Point(1, y), Area(label_w + 2, label_h - 1)), label_bgcol); - canvas.draw_string(Point(1, y - 1), default_font, label_fgcol, _label); + canvas.draw_string(Point(1, y - 1), font, label_fgcol, _label); canvas.draw_box(Rect(Point(1, y + label_h - 1), Area(label_w + 2, 1)), Color(0, 0, 0)); canvas.draw_box(Rect(Point(label_w + 2, y), Area(1, label_h - 1)), _color); canvas.draw_box(Rect(Point(label_w + 3, y), Area(1, label_h - 1)), Color(0, 0, 0)); @@ -170,7 +170,7 @@ class Log_entry canvas.draw_box(Rect(Point(1, y), Area(1000, label_h)), text_bgcol); /* draw log text */ - canvas.draw_string(Point(label_w + 6, y), default_font, text_fgcol, _text); + canvas.draw_string(Point(label_w + 6, y), font, text_fgcol, _text); } /** @@ -186,6 +186,7 @@ class Log_window private: Canvas_base &_canvas; + Font const &_font; Log_entry _entries[LOG_H]; /* log entries */ int _dst_entry = 0; /* destination entry for next write */ int _view_pos = 0; /* current view port on the entry array */ @@ -199,7 +200,8 @@ class Log_window /** * Constructor */ - Log_window(Canvas_base &canvas) : _canvas(canvas) { } + Log_window(Canvas_base &canvas, Font const &font) + : _canvas(canvas), _font(font) { } /** * Write log entry @@ -241,12 +243,12 @@ class Log_window _dirty = false; } - int line_h = default_font.str_h(" "); + int line_h = _font.bounding_box().h(); int curr_session_id = -1; for (int i = 0, y = 0; i < LOG_H; i++, y += line_h) { Log_entry *le = &_entries[(i + _view_pos) % LOG_H]; - le->draw(_canvas, y, curr_session_id != le->id()); + le->draw(_canvas, _font, y, curr_session_id != le->id()); curr_session_id = le->id(); } @@ -394,9 +396,13 @@ struct Nitlog::Main { Env &_env; + Tff_font::Static_glyph_buffer<4096> _glyph_buffer { }; + + Tff_font _font { _binary_mono_tff_start, _glyph_buffer }; + /* calculate size of log view in pixels */ - unsigned const _win_w = default_font.str_w(" ") * LOG_W + 2; - unsigned const _win_h = default_font.str_h(" ") * LOG_H + 2; + unsigned const _win_w = _font.bounding_box().w() * LOG_W + 2; + unsigned const _win_h = _font.bounding_box().h() * LOG_H + 2; /* init sessions to the required external services */ Nitpicker::Connection _nitpicker { _env }; @@ -418,7 +424,7 @@ struct Nitlog::Main Canvas _canvas { _fb_ds.local_addr(), ::Area(_win_w, _win_h) }; - Log_window _log_window { _canvas }; + Log_window _log_window { _canvas, _font }; void _init_canvas() { diff --git a/repos/gems/src/app/decorator/canvas.h b/repos/gems/src/app/decorator/canvas.h index 50539227fb..3bc594ac47 100644 --- a/repos/gems/src/app/decorator/canvas.h +++ b/repos/gems/src/app/decorator/canvas.h @@ -83,7 +83,8 @@ class Decorator::Canvas : public Decorator::Canvas_base void draw_text(Point pos, Font const &font, Color color, char const *string) override { - Text_painter::paint(_surface, pos, font, color, string); + Text_painter::paint(_surface, Text_painter::Position(pos.x(), pos.y()), + font, color, string); } void draw_texture(Point pos, Texture_id id) diff --git a/repos/gems/src/app/decorator/default_font.cc b/repos/gems/src/app/decorator/default_font.cc index 5ebb71a8a6..4abe952733 100644 --- a/repos/gems/src/app/decorator/default_font.cc +++ b/repos/gems/src/app/decorator/default_font.cc @@ -11,6 +11,9 @@ * under the terms of the GNU Affero General Public License version 3. */ +/* Genode includes */ +#include + /* local includes */ #include "canvas.h" @@ -26,9 +29,10 @@ extern char _binary_droidsansb10_tff_start[]; */ Decorator::Font &Decorator::default_font() { - static Font font(_binary_droidsansb10_tff_start); + static Tff_font::Static_glyph_buffer<4096> glyph_buffer { }; + + static Tff_font font { _binary_droidsansb10_tff_start, glyph_buffer }; + return font; } - - diff --git a/repos/gems/src/app/decorator/window.cc b/repos/gems/src/app/decorator/window.cc index efa4784392..44e4f8fb7c 100644 --- a/repos/gems/src/app/decorator/window.cc +++ b/repos/gems/src/app/decorator/window.cc @@ -122,8 +122,8 @@ void Decorator::Window::draw(Decorator::Canvas_base &canvas, char const * const text = _title.string(); - Area const label_area(default_font().str_w(text), - default_font().str_h(text)); + Area const label_area(default_font().string_width(text).decimal(), + default_font().bounding_box().h()); /* * Position the text in the center of the window. diff --git a/repos/gems/src/app/menu_view/label_widget.h b/repos/gems/src/app/menu_view/label_widget.h index 11bfabf618..3d0047abca 100644 --- a/repos/gems/src/app/menu_view/label_widget.h +++ b/repos/gems/src/app/menu_view/label_widget.h @@ -44,8 +44,8 @@ struct Menu_view::Label_widget : Widget if (!font) return Area(0, 0); - return Area(font->str_w(text.string()), - font->str_h(text.string())); + return Area(font->string_width(text.string()).decimal(), + font->bounding_box().h()); } void draw(Surface &pixel_surface, @@ -59,13 +59,15 @@ struct Menu_view::Label_widget : Widget int const dx = (int)geometry().w() - text_size.w(), dy = (int)geometry().h() - text_size.h(); - Point const centered = Point(dx/2, dy/2); + Point const centered = at + Point(dx/2, dy/2); - Text_painter::paint(pixel_surface, at + centered, *font, - Color(0, 0, 0), text.string()); + Text_painter::paint(pixel_surface, + Text_painter::Position(centered.x(), centered.y()), + *font, Color(0, 0, 0), text.string()); - Text_painter::paint(alpha_surface, at + centered, *font, - Color(255, 255, 255), text.string()); + Text_painter::paint(alpha_surface, + Text_painter::Position(centered.x(), centered.y()), + *font, Color(255, 255, 255), text.string()); } }; diff --git a/repos/gems/src/app/menu_view/style_database.h b/repos/gems/src/app/menu_view/style_database.h index 038670bb9c..ffc3cea2b6 100644 --- a/repos/gems/src/app/menu_view/style_database.h +++ b/repos/gems/src/app/menu_view/style_database.h @@ -14,6 +14,9 @@ #ifndef _STYLE_DATABASE_H_ #define _STYLE_DATABASE_H_ +/* Genode includes */ +#include + /* gems includes */ #include #include @@ -55,8 +58,12 @@ class Menu_view::Style_database struct Font_entry : List::Element { String path; - File tff_file; - Text_painter::Font font; + + File tff_file; + + Tff_font::Allocated_glyph_buffer glyph_buffer; + + Tff_font font; /** * Constructor @@ -67,7 +74,8 @@ class Menu_view::Style_database : path(path), tff_file(path, alloc), - font(tff_file.data()) + glyph_buffer(tff_file.data(), alloc), + font(tff_file.data(), glyph_buffer) { } }; diff --git a/repos/gems/src/app/themed_decorator/theme.cc b/repos/gems/src/app/themed_decorator/theme.cc index 94a1a61cfe..3203f0389e 100644 --- a/repos/gems/src/app/themed_decorator/theme.cc +++ b/repos/gems/src/app/themed_decorator/theme.cc @@ -13,7 +13,7 @@ /* Genode includes */ #include -#include +#include #include #include @@ -90,7 +90,8 @@ texture_by_element_type(Genode::Ram_session &ram, Genode::Region_map &rm, static Text_painter::Font const &title_font(Genode::Allocator &alloc) { static File tff_file("theme/font.tff", alloc); - static Text_painter::Font font(tff_file.data()); + static Tff_font::Allocated_glyph_buffer glyph_buffer(tff_file.data(), alloc); + static Tff_font font(tff_file.data(), glyph_buffer); return font; } @@ -267,13 +268,14 @@ void Decorator::Theme::draw_title(Decorator::Pixel_surface &pixel_surface, Text_painter::Font const &font = title_font(_alloc); - Area const label_area(font.str_w(title), font.str_h(title)); + Area const label_area(font.string_width(title).decimal(), + font.bounding_box().h()); Rect const surface_rect(Point(0, 0), pixel_surface.size()); Rect const title_rect = absolute(title_geometry(), surface_rect); - Point const centered_text_pos = title_rect.center(label_area) - Point(0, 1); + Point const pos = title_rect.center(label_area) - Point(0, 1); - Text_painter::paint(pixel_surface, centered_text_pos, font, - Genode::Color(0, 0, 0), title); + Text_painter::paint(pixel_surface, Text_painter::Position(pos.x(), pos.y()), + font, Genode::Color(0, 0, 0), title); } diff --git a/repos/gems/src/server/terminal/draw_glyph.h b/repos/gems/src/server/terminal/draw_glyph.h deleted file mode 100644 index f06121b6c0..0000000000 --- a/repos/gems/src/server/terminal/draw_glyph.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * \brief Function for drawing the glyphs of terminal characters - * \author Norman Feske - * \date 2018-02-06 - */ - -/* - * Copyright (C) 2018 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _DRAW_GLYPH_H_ -#define _DRAW_GLYPH_H_ - -/* Genode includes */ -#include - -template -inline void draw_glyph(Genode::Color fg_color, - Genode::Color bg_color, - const unsigned char *glyph_base, - unsigned glyph_width, - unsigned glyph_img_width, - unsigned glyph_img_height, - unsigned cell_width, - PT *fb_base, - unsigned fb_width) -{ - PT fg_pixel(fg_color.r, fg_color.g, fg_color.b); - PT bg_pixel(bg_color.r, bg_color.g, bg_color.b); - - unsigned const horizontal_gap = cell_width - - Genode::min(glyph_width, cell_width); - - unsigned const left_gap = horizontal_gap / 2; - unsigned const right_gap = horizontal_gap - left_gap; - - /* - * Clear gaps to the left and right of the character if the character's - * with is smaller than the cell width. - */ - if (horizontal_gap) { - - PT *line = fb_base; - for (unsigned y = 0 ; y < glyph_img_height; y++, line += fb_width) { - - for (unsigned x = 0; x < left_gap; x++) - line[x] = bg_pixel; - - for (unsigned x = cell_width - right_gap; x < cell_width; x++) - line[x] = bg_pixel; - } - } - - /* center glyph horizontally within its cell */ - fb_base += left_gap; - - for (unsigned y = 0 ; y < glyph_img_height; y++) { - for (unsigned x = 0; x < glyph_width; x++) - fb_base[x] = PT::mix(bg_pixel, fg_pixel, glyph_base[x]); - - fb_base += fb_width; - glyph_base += glyph_img_width; - } -} - -#endif /* _DRAW_GLYPH_H_ */ diff --git a/repos/gems/src/server/terminal/font_family.h b/repos/gems/src/server/terminal/font_family.h index 51782fb964..e3bc72c472 100644 --- a/repos/gems/src/server/terminal/font_family.h +++ b/repos/gems/src/server/terminal/font_family.h @@ -40,8 +40,8 @@ class Terminal::Font_family */ Font const &font(Font_face) const { return _regular; } - unsigned cell_width() const { return _regular.str_w("m"); } - unsigned cell_height() const { return _regular.str_h("m"); } + unsigned cell_width() const { return _regular.bounding_box().w(); } + unsigned cell_height() const { return _regular.bounding_box().h(); } }; #endif /* _FONT_FAMILY_H_ */ diff --git a/repos/gems/src/server/terminal/main.cc b/repos/gems/src/server/terminal/main.cc index 09f0201bf4..f53ec8b3c4 100644 --- a/repos/gems/src/server/terminal/main.cc +++ b/repos/gems/src/server/terminal/main.cc @@ -21,6 +21,7 @@ #include #include #include +#include /* terminal includes */ #include @@ -52,7 +53,10 @@ struct Terminal::Main : Character_consumer */ static char const *_font_data(Xml_node config); - Reconstructible _font { _font_data(_config.xml()) }; + Tff_font::Static_glyph_buffer<4096> _glyph_buffer { }; + + Reconstructible _font { _font_data(_config.xml()), _glyph_buffer }; + Reconstructible _font_family { *_font }; unsigned char *_keymap = Terminal::usenglish_keymap; @@ -193,7 +197,7 @@ void Terminal::Main::_handle_config() Xml_node const config = _config.xml(); - _font.construct(_font_data(config)); + _font.construct(_font_data(config), _glyph_buffer); _font_family.construct(*_font); /* diff --git a/repos/gems/src/server/terminal/text_screen_surface.h b/repos/gems/src/server/terminal/text_screen_surface.h index 9f96f538e5..11a216cabf 100644 --- a/repos/gems/src/server/terminal/text_screen_surface.h +++ b/repos/gems/src/server/terminal/text_screen_surface.h @@ -22,10 +22,10 @@ /* nitpicker graphic back end */ #include +#include /* local includes */ #include "font_family.h" -#include "draw_glyph.h" #include "color_palette.h" #include "framebuffer.h" @@ -69,14 +69,23 @@ class Terminal::Text_screen_surface { Font const ®ular_font = _font_family.font(Font_face::REGULAR); - unsigned const glyph_height = regular_font.img_h, - glyph_step_x = regular_font.wtab['m']; + Area const cell_size = regular_font.bounding_box(); + + unsigned const glyph_height = regular_font.bounding_box().h(), + glyph_step_x = regular_font.bounding_box().w(); unsigned const fb_width = _framebuffer.w(), fb_height = _framebuffer.h(); + int const clip_top = 0, clip_bottom = fb_height, + clip_left = 0, clip_right = fb_width; + PT *fb_base = _framebuffer.pixel(); + Surface surface(fb_base, Area(_framebuffer.w(), _framebuffer.h())); + + unsigned const fg_alpha = 255; + unsigned y = 0; for (unsigned line = 0; line < _cell_array.num_lines(); line++) { @@ -92,41 +101,39 @@ class Terminal::Text_screen_surface if (ascii == 0) ascii = ' '; - unsigned char const *glyph_base = font.img + font.otab[ascii]; + Text_painter::Codepoint const c { ascii }; - unsigned glyph_width = regular_font.wtab[ascii]; + font.apply_glyph(c, [&] (Glyph_painter::Glyph const &glyph) { - if (x + glyph_width > fb_width) - break; + Color_palette::Highlighted const highlighted { cell.highlight() }; + Color_palette::Inverse const inverse { cell.inverse() }; - Color_palette::Highlighted const highlighted { cell.highlight() }; - Color_palette::Inverse const inverse { cell.inverse() }; + Color fg_color = + _palette.foreground(Color_palette::Index{cell.colidx_fg()}, + highlighted, inverse); - Color fg_color = - _palette.foreground(Color_palette::Index{cell.colidx_fg()}, - highlighted, inverse); + Color bg_color = + _palette.background(Color_palette::Index{cell.colidx_bg()}, + highlighted, inverse); - Color bg_color = - _palette.background(Color_palette::Index{cell.colidx_bg()}, - highlighted, inverse); + if (cell.has_cursor()) { + fg_color = Color( 63, 63, 63); + bg_color = Color(255, 255, 255); + } - if (cell.has_cursor()) { - fg_color = Color( 63, 63, 63); - bg_color = Color(255, 255, 255); - } + PT const pixel(fg_color.r, fg_color.g, fg_color.b); - draw_glyph(fg_color, bg_color, - glyph_base, glyph_width, - (unsigned)font.img_w, (unsigned)font.img_h, - glyph_step_x, fb_base + x, fb_width); + Box_painter::paint(surface, Rect(Point(x, y), cell_size), bg_color); - x += glyph_step_x; + Glyph_painter::paint(Glyph_painter::Position((int)x, (int)y), + glyph, fb_base, fb_width, + clip_top, clip_bottom, clip_left, clip_right, + pixel, fg_alpha); + x += glyph_step_x; + }); } } - y += glyph_height; - fb_base += fb_width*glyph_height; - - if (y + glyph_height > fb_height) break; + y += glyph_height; } int first_dirty_line = 10000, diff --git a/repos/os/include/nitpicker_gfx/glyph_painter.h b/repos/os/include/nitpicker_gfx/glyph_painter.h new file mode 100644 index 0000000000..fdf3af2138 --- /dev/null +++ b/repos/os/include/nitpicker_gfx/glyph_painter.h @@ -0,0 +1,148 @@ +/* + * \brief Functor for drawing glyphs + * \author Norman Feske + * \date 2006-08-04 + */ + +/* + * Copyright (C) 2006-2018 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__NITPICKER_GFX__GLYPH_PAINTER_H_ +#define _INCLUDE__NITPICKER_GFX__GLYPH_PAINTER_H_ + +#include +#include +#include + + +struct Glyph_painter +{ + /** + * Subpixel positions are represented as fixpoint numbers that use 24 bits + * for the decimal and 8 bits for the fractional part. + */ + struct Fixpoint_number + { + int value; + + Fixpoint_number(float value) : value(value*256) { }; + + Fixpoint_number(int decimal) : value(decimal << 8) { }; + + int decimal() const { return value >> 8; } + }; + + typedef Genode::Point Position; + + + struct Glyph + { + unsigned const width; + unsigned const height; + unsigned const vpos; + + Fixpoint_number const advance; + + struct Opacity { unsigned char value; }; + + /** + * Pointer to opacity values (0 = transparent, 255 = opaque) + * + * The 'values' buffer contains the glyph horizontally scaled by four. + * Its size is width*4*height bytes. The first row (four values) of each + * line as well as the last line contains padding space, which does not + * need to be drawn in order to obtain the complete shape. + */ + Opacity const * const values; + + unsigned num_values() const { return 4*width*height; } + }; + + + /** + * Draw single glyph on a 'dst' buffer, with clipping applied + * + * In contrast to most painter functions, which operate on a 'Surface', + * this function has a lower-level interface. It is intended as a utility + * called by painter implementations, not by applications directly. + */ + template + static inline void paint(Position const position, Glyph const &glyph, + PT *dst, unsigned const dst_line_len, + int const clip_top, int const clip_bottom, + int const clip_left, int const clip_right, + PT const color, int const alpha) + { + Fixpoint_number const x = position.x(); + int const y = position.y().decimal(); + + int const dst_y1 = y + glyph.vpos, + dst_y2 = dst_y1 + glyph.height; + + unsigned const clipped_from_top = clip_top > dst_y1 + ? clip_top - dst_y1 : 0; + + unsigned const clipped_from_bottom = dst_y2 > clip_bottom + ? dst_y2 - clip_bottom : 0; + + if (clipped_from_top + clipped_from_bottom >= glyph.height) + return; + + unsigned const num_lines = glyph.height - clipped_from_top + - clipped_from_bottom; + int const w = glyph.width; + int const start = Genode::max(0, clip_left - x.decimal()); + int const end = Genode::min(w - 1, clip_right - x.decimal()); + + int const dst_x = start + ((x.value) >> 8); + int const glyph_x = start*4 + 3 - ((x.value & 0xc0) >> 6); + + unsigned const glyph_line_len = 4*glyph.width; + + PT *dst_column = dst + dst_x + + dst_line_len*(dst_y1 + clipped_from_top); + + typedef Glyph::Opacity Opacity; + Opacity const *glyph_column = glyph.values + glyph_x + + glyph_line_len*clipped_from_top; + + /* iterate over the visible columns of the glyph */ + for (int i = start; i < end; i++) { + + /* weights of the two sampled values (horizontal neighbors)*/ + int const u0 = x.value*4 & 0xff; + int const u1 = 0x100 - u0; + + PT *d = dst_column; + Opacity const *s = glyph_column; + + /* iterate over one column */ + for (unsigned j = 0; j < num_lines; j++) { + + /* sample values from glyph image */ + unsigned const v0 = s->value; + unsigned const v1 = (s + 1)->value; + + /* apply weights */ + int const value = (v0*u0 + v1*u1) >> 8; + + /* transfer pixel */ + if (value) + *d = (value == 255 && alpha == 255) + ? color : PT::mix(*d, color, (alpha*value) >> 8); + + s += glyph_line_len; + d += dst_line_len; + } + + dst_column += 1; + glyph_column += 4; + } + } +}; + +#endif /* _INCLUDE__NITPICKER_GFX__GLYPH_PAINTER_H_ */ diff --git a/repos/os/include/nitpicker_gfx/text_painter.h b/repos/os/include/nitpicker_gfx/text_painter.h index bd080bc1a2..eba14d7edb 100644 --- a/repos/os/include/nitpicker_gfx/text_painter.h +++ b/repos/os/include/nitpicker_gfx/text_painter.h @@ -1,11 +1,11 @@ /* - * \brief Functor for drawing text into a surface + * \brief Functor for drawing text on a surface * \author Norman Feske * \date 2006-08-04 */ /* - * Copyright (C) 2006-2017 Genode Labs GmbH + * Copyright (C) 2006-2018 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -14,119 +14,144 @@ #ifndef _INCLUDE__NITPICKER_GFX__TEXT_PAINTER_H_ #define _INCLUDE__NITPICKER_GFX__TEXT_PAINTER_H_ -#include -#include +#include +#include +#include struct Text_painter { - class Font - { - private: - - typedef Genode::int32_t int32_t; - typedef Genode::size_t size_t; - - public: - - unsigned char const *img; /* font image */ - int const img_w, img_h; /* size of font image */ - int32_t const *otab; /* offset table */ - int32_t const *wtab; /* width table */ - - /** - * Construct font from a TFF data block - */ - Font(const char *tff) - : - img((unsigned char *)(tff + 2056)), - - img_w(*((int32_t *)(tff + 2048))), - img_h(*((int32_t *)(tff + 2052))), - - otab((int32_t *)(tff)), - wtab((int32_t *)(tff + 1024)) - { } - - /** - * Calculate width of string when printed with the font - */ - int str_w(const char *sstr, size_t len = ~0UL) const - { - const unsigned char *str = (const unsigned char *)sstr; - int res = 0; - for (; str && *str && len; len--, str++) res += wtab[*str]; - return res; - } - - /** - * Calculate height of string when printed with the font - */ - int str_h(const char *, size_t = ~0UL) const { return img_h; } - }; - - typedef Genode::Surface_base::Point Point; typedef Genode::Surface_base::Area Area; typedef Genode::Surface_base::Rect Rect; + typedef Genode::Codepoint Codepoint; + + typedef Glyph_painter::Fixpoint_number Fixpoint_number; + typedef Glyph_painter::Position Position; + typedef Glyph_painter::Glyph Glyph; + /*************************************** + ** Interface for accessing font data ** + ***************************************/ + + class Font : public Genode::Interface + { + protected: + + struct Apply_fn : Genode::Interface + { + virtual void apply(Glyph const &) const = 0; + }; + + virtual void _apply_glyph(Codepoint c, Apply_fn const &) const = 0; + + public: + + template + void apply_glyph(Codepoint c, FN const &fn) const + { + /* helper to pass lambda 'fn' to virtual '_apply_glyph' method */ + struct Wrapped_fn : Apply_fn + { + FN const &_fn; + void apply(Glyph const &glyph) const override { _fn(glyph); } + Wrapped_fn(FN const &fn) : _fn(fn) { } + }; + + _apply_glyph(c, Wrapped_fn(fn)); + } + + struct Advance_info + { + unsigned const width; + Fixpoint_number const advance; + }; + + virtual Advance_info advance_info(Codepoint c) const = 0; + + /** + * Return distance from the top of a glyph the baseline of the font + */ + virtual unsigned baseline() const = 0; + + /** + * Return the bounding box that fits each single glyph of the font + */ + virtual Area bounding_box() const = 0; + + /** + * Compute width of UTF8 string in pixels when rendered with the font + */ + Fixpoint_number string_width(Genode::Utf8_ptr utf8, unsigned len = ~0U) const + { + Fixpoint_number result { (int)0 }; + + for (; utf8.complete() && len--; utf8 = utf8.next()) + result.value += advance_info(utf8.codepoint()).advance.value; + + return result; + } + }; + + + /** + * Paint UTF8 string to surface + */ template static inline void paint(Genode::Surface &surface, - Point p, + Position position, Font const &font, Genode::Color color, - char const *sstr) + char const *string) { - unsigned char const *str = (unsigned char const *)sstr; - int x = p.x(), y = p.y(); + /* use sub-pixel positioning horizontally */ + Fixpoint_number x = position.x(); + Fixpoint_number const y = position.y(); - unsigned char const *src = font.img; - int d, h = font.img_h; + int const clip_top = surface.clip().y1(), + clip_bottom = surface.clip().y2() + 1, + clip_left = surface.clip().x1(), + clip_right = surface.clip().x2() + 1; - /* check top clipping */ - if ((d = surface.clip().y1() - y) > 0) { - src += d*font.img_w; - y += d; - h -= d; + Genode::Utf8_ptr utf8(string); + + /* skip glyphs hidden behind left clipping border */ + bool skip = true; + while (skip && utf8.complete()) { + auto const glyph = font.advance_info(utf8.codepoint()); + skip = x.decimal() + (int)glyph.width < clip_left; + if (skip) { + x.value += glyph.advance.value; + utf8 = utf8.next(); + } } - /* check bottom clipping */ - if ((d = y + h -1 - surface.clip().y2()) > 0) - h -= d; + int const x_start = x.decimal(); - if (h < 1) return; + unsigned const dst_line_len = surface.size().w(); - /* skip hidden glyphs */ - for ( ; *str && (x + font.wtab[*str] < surface.clip().x1()); ) - x += font.wtab[*str++]; + PT * const dst = surface.addr(); - int const x_start = x; - - PT *dst = surface.addr() + y*surface.size().w(); - - PT const pix(color.r, color.g, color.b); + PT const pixel(color.r, color.g, color.b); int const alpha = color.a; /* draw glyphs */ - for ( ; *str && (x <= surface.clip().x2()); str++) { + for ( ; utf8.complete() && (x.decimal() <= clip_right); utf8 = utf8.next()) { - int const w = font.wtab[*str]; - int const start = Genode::max(0, surface.clip().x1() - x); - int const end = Genode::min(w - 1, surface.clip().x2() - x); + font.apply_glyph(utf8.codepoint(), [&] (Glyph const &glyph) { - PT *d = dst + x; - unsigned char const *s = src + font.otab[*str]; + Glyph_painter::paint(Position(x, y), glyph, dst, dst_line_len, + clip_top, clip_bottom, clip_left, clip_right, + pixel, alpha); - for (int j = 0; j < h; j++, s += font.img_w, d += surface.size().w()) - for (int i = start; i <= end; i++) - if (s[i]) - d[i] = (s[i] == 255 && alpha == 255) - ? pix : PT::mix(d[i], pix, (alpha*s[i]) >> 8); - x += w; + x.value += glyph.advance.value; + }); } - surface.flush_pixels(Rect(Point(x_start, y), Area(x - x_start + 1, h))); + surface.flush_pixels(Rect(Point(x_start, y.decimal()), + Area(x.decimal() - x_start + 1, + font.bounding_box().h()))); } }; diff --git a/repos/os/include/nitpicker_gfx/tff_font.h b/repos/os/include/nitpicker_gfx/tff_font.h new file mode 100644 index 0000000000..22e3965254 --- /dev/null +++ b/repos/os/include/nitpicker_gfx/tff_font.h @@ -0,0 +1,237 @@ +/* + * \brief Implementation of 'Text_painter::Font' using a trivial font format + * \author Norman Feske + * \date 2018-03-12 + */ + +/* + * Copyright (C) 2018 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__NITPICKER_GFX__TFF_FONT_H_ +#define _INCLUDE__NITPICKER_GFX__TFF_FONT_H_ + +#include +#include + +class Tff_font : public Text_painter::Font +{ + public: + + struct Glyph_buffer + { + char * const ptr; + Genode::size_t const size; + }; + + template + struct Static_glyph_buffer : Glyph_buffer + { + char _data[SIZE]; + Static_glyph_buffer() : Glyph_buffer({_data, sizeof(_data)}) { } + }; + + struct Allocated_glyph_buffer : Tff_font::Glyph_buffer + { + Genode::Allocator &_alloc; + + Allocated_glyph_buffer(void const *tff, Genode::Allocator &alloc) + : + Tff_font::Glyph_buffer({ + (char *)alloc.alloc(Tff_font::glyph_buffer_size(tff)), + Tff_font::glyph_buffer_size(tff) }), + _alloc(alloc) + { } + + ~Allocated_glyph_buffer() + { + _alloc.free(ptr, size); + } + }; + + private: + + typedef Genode::int32_t int32_t; + + typedef Text_painter::Codepoint Codepoint; + typedef Text_painter::Area Area; + typedef Text_painter::Glyph Glyph; + + Glyph_buffer &_buf; + + enum { NUM_GLYPHS = 256, PAD_LEFT = 1 }; + + struct Tff + { + unsigned char const *img; /* font image */ + int const img_w, img_h; /* size of font image */ + int32_t const *otab; /* offset table */ + int32_t const *wtab; /* width table */ + + Tff(void const *data) + : + img((unsigned char *)data + 2056), + + img_w(*((int32_t *)((unsigned char *)data + 2048))), + img_h(*((int32_t *)((unsigned char *)data + 2052))), + + otab((int32_t *)(data)), + wtab((int32_t *)((unsigned char *)data + 1024)) + { } + + Area bounding_box() const + { + unsigned max_w = 0; + for (unsigned i = 0; i < NUM_GLYPHS; i++) + max_w = Genode::max(max_w, (unsigned)wtab[i]); + + return Area(max_w, img_h); + } + + bool _glyph_line_empty(unsigned char c, unsigned y) const + { + unsigned char const * const line = img + otab[c] + y*img_w; + for (unsigned i = 0; i < (unsigned)wtab[c]; i++) + if (line[i]) + return false; + + return true; + } + + struct Vertical_metrics + { + unsigned vpos; + unsigned height; + }; + + Vertical_metrics vertical_metrics(unsigned char c) const + { + unsigned y_start = 0; + unsigned y_end = img_h; + + /* determine empty lines below glyph */ + for (; y_end > 0; y_end--) + if (!_glyph_line_empty(c, y_end - 1)) + break; + + /* determine empty lines above glyph */ + for (; y_start < (unsigned)img_h; y_start++) + if (!_glyph_line_empty(c, y_start)) + break; + + return Vertical_metrics { + .vpos = y_start, + .height = (y_end > y_start) ? y_end - y_start : 0 + }; + } + }; + + Tff const _tff; + + Tff::Vertical_metrics _vertical_metrics[NUM_GLYPHS]; + + Area const _bounding_box = _tff.bounding_box(); + + /* + * Noncopyable + */ + Tff_font(Tff_font const &); + Tff_font &operator = (Tff_font const &); + + public: + + struct Invalid_format : Genode::Exception { }; + struct Insufficient_glyph_buffer : Genode::Exception { }; + + /** + * Constructor + * + * \param tff font data + * \param glyph_buffer buffer for rendered glyph + * + * \throw Invalid_format + * \throw Insufficient_glyph_buffer + * + * The 'glyph_buffer' should be dimensioned via 'glyph_buffer_size()'. + */ + Tff_font(void const *tff, Glyph_buffer &glyph_buffer) + : + _buf(glyph_buffer), _tff(tff) + { + if (_tff.img_h < 1 || _tff.img_w < 1) + throw Invalid_format(); + + if (_buf.size < glyph_buffer_size(tff)) + throw Insufficient_glyph_buffer(); + + for (unsigned i = 0; i < NUM_GLYPHS; i++) + _vertical_metrics[i] = _tff.vertical_metrics(i); + } + + /** + * Return required glyph-buffer size for a given font + */ + static Genode::size_t glyph_buffer_size(void const *tff) + { + /* account for four-times horizontal supersampling */ + return Tff(tff).bounding_box().count()*4; + } + + void _apply_glyph(Codepoint c, Apply_fn const &fn) const override + { + unsigned const ascii = c.value & 0xff; + + unsigned const w = _tff.wtab[ascii], + h = _vertical_metrics[ascii].height, + vpos = _vertical_metrics[ascii].vpos; + + unsigned char const *glyph_line = _tff.img + _tff.otab[ascii] + + vpos*_tff.img_w; + + Glyph::Opacity *dst = (Glyph::Opacity *)_buf.ptr; + + for (unsigned j = 0; j < h; j++) { + + /* insert padding in front */ + for (unsigned k = 0; k < PAD_LEFT*4; k++) + *dst++ = Glyph::Opacity { 0 }; + + /* copy line from font image to glyph */ + for (unsigned i = 0; i < w; i++) { + Glyph::Opacity const opacity { glyph_line[i] }; + for (unsigned k = 0; k < 4; k++) + *dst++ = opacity; + } + glyph_line += _tff.img_w; + } + + Glyph const glyph { .width = w + PAD_LEFT, + .height = h, + .vpos = vpos, + .advance = (int)w, + .values = (Glyph::Opacity *)_buf.ptr }; + fn.apply(glyph); + } + + Advance_info advance_info(Codepoint c) const override + { + unsigned const ascii = c.value & 0xff; + unsigned const w = _tff.wtab[ascii]; + + return Advance_info { .width = w + PAD_LEFT, + .advance = (int)w }; + } + + unsigned baseline() const override + { + Tff::Vertical_metrics const m = _vertical_metrics['m']; + return m.vpos + m.height; + } + + Area bounding_box() const override { return _bounding_box; } +}; + +#endif /* _INCLUDE__NITPICKER_GFX__TFF_FONT_H_ */ diff --git a/repos/os/run/demo.run b/repos/os/run/demo.run index 59a1d3a65b..ebb0959869 100644 --- a/repos/os/run/demo.run +++ b/repos/os/run/demo.run @@ -261,7 +261,7 @@ puts $launchpad_config_fd { - + diff --git a/repos/os/src/app/status_bar/main.cc b/repos/os/src/app/status_bar/main.cc index 37f811988e..c2fb851981 100644 --- a/repos/os/src/app/status_bar/main.cc +++ b/repos/os/src/app/status_bar/main.cc @@ -19,7 +19,7 @@ #include #include #include -#include +#include namespace Status_bar { @@ -61,7 +61,8 @@ struct Status_bar::Buffer Attached_dataspace _fb_ds; - Text_painter::Font const _font { &_binary_default_tff_start }; + Tff_font::Static_glyph_buffer<4096> _glyph_buffer { }; + Tff_font _font { &_binary_default_tff_start, _glyph_buffer }; Buffer(Region_map &rm, Nitpicker::Connection &nitpicker) : @@ -74,8 +75,9 @@ struct Status_bar::Buffer for (int j = -1; j <= 1; j++) for (int i = -1; i <= 1; i++) if (i || j) - Text_painter::paint(surface, pos + Point(i, j), _font, - Color(0, 0, 0), s); + Text_painter::paint(surface, + Text_painter::Position(pos.x() + i, pos.y() + j), + _font, Color(0, 0, 0), s); } template @@ -91,20 +93,21 @@ struct Status_bar::Buffer pos = pos + Point(1, 1); _draw_outline(surface, pos, domain_name.string()); - Text_painter::paint(surface, pos, _font, domain_text_color, - domain_name.string()); + Text_painter::paint(surface, Text_painter::Position(pos.x(), pos.y()), + _font, domain_text_color, domain_name.string()); - pos = pos + Point(_font.str_w(domain_name.string()) + LABEL_GAP, 0); + pos = pos + Point(_font.string_width(domain_name.string()).decimal() + LABEL_GAP, 0); _draw_outline(surface, pos, label.string()); - Text_painter::paint(surface, pos, _font, label_text_color, label.string()); + Text_painter::paint(surface, Text_painter::Position(pos.x(), pos.y()), + _font, label_text_color, label.string()); } Area _label_size(Domain_name const &domain_name, Label const &label) const { - return Area(_font.str_w(domain_name.string()) + LABEL_GAP - + _font.str_w(label.string()) + 2, - _font.str_h(domain_name.string()) + 2); + return Area(_font.string_width(domain_name.string()).decimal() + LABEL_GAP + + _font.string_width(label.string()).decimal() + 2, + _font.bounding_box().h() + 2); } void draw(Domain_name const &, Label const &, Color); diff --git a/repos/os/src/server/nitpicker/background.h b/repos/os/src/server/nitpicker/background.h index e4deaa93c6..327264de86 100644 --- a/repos/os/src/server/nitpicker/background.h +++ b/repos/os/src/server/nitpicker/background.h @@ -50,7 +50,7 @@ struct Nitpicker::Background : private Texture_base, View_component int frame_size(Focus const &) const override { return 0; } void frame(Canvas_base &, Focus const &) const override { } - void draw(Canvas_base &canvas, Focus const &) const override + void draw(Canvas_base &canvas, Font const &, Focus const &) const override { Rect const view_rect = abs_geometry(); Clip_guard clip_guard(canvas, view_rect); diff --git a/repos/os/src/server/nitpicker/canvas.h b/repos/os/src/server/nitpicker/canvas.h index ea6d0b5e4b..d3e1140b09 100644 --- a/repos/os/src/server/nitpicker/canvas.h +++ b/repos/os/src/server/nitpicker/canvas.h @@ -24,6 +24,8 @@ namespace Nitpicker { struct Canvas_base; template class Canvas; + + typedef Text_painter::Font Font; } @@ -92,10 +94,11 @@ class Nitpicker::Canvas : public Canvas_base, public Surface_base::Flusher allow_alpha); } - void draw_text(Point pos, Text_painter::Font const &font, + void draw_text(Point pos, Font const &font, Color color, char const *string) { - Text_painter::paint(_surface, pos, font, color, string); + Text_painter::paint(_surface, Text_painter::Position(pos.x(), pos.y()), + font, color, string); } }; diff --git a/repos/os/src/server/nitpicker/draw_label.h b/repos/os/src/server/nitpicker/draw_label.h index a2f23a3888..60ad92f595 100644 --- a/repos/os/src/server/nitpicker/draw_label.h +++ b/repos/os/src/server/nitpicker/draw_label.h @@ -20,8 +20,6 @@ namespace Nitpicker { - extern Text_painter::Font default_font; - /* * Gap between session label and view title in pixels */ @@ -30,12 +28,13 @@ namespace Nitpicker { /** * Draw black outline of string */ - inline void draw_string_outline(Canvas_base &canvas, Point pos, char const *s) + inline void draw_string_outline(Canvas_base &canvas, Text_painter::Font const &font, + Point pos, char const *s) { for (int j = -1; j <= 1; j++) for (int i = -1; i <= 1; i++) if (i || j) - canvas.draw_text(pos + Point(i, j), default_font, black(), s); + canvas.draw_text(pos + Point(i, j), font, black(), s); } @@ -45,9 +44,10 @@ namespace Nitpicker { * \param sl session label string * \param vt view title string */ - inline Area label_size(const char *sl, const char *vt) { - return Area(default_font.str_w(sl) + LABEL_GAP + default_font.str_w(vt) + 2, - default_font.str_h(sl) + 2); } + inline Area label_size(Font const &font, const char *sl, const char *vt) { + return Area(font.string_width(sl).decimal() + LABEL_GAP + + font.string_width(vt).decimal() + 2, + font.bounding_box().h() + 2); } /** @@ -58,19 +58,19 @@ namespace Nitpicker { * policy. In contrast, the view title can individually be defined by the * application. */ - static inline void draw_label(Canvas_base &canvas, Point pos, + static inline void draw_label(Canvas_base &canvas, Font const &font, Point pos, char const *session_label, Color session_label_color, char const *view_title, Color view_title_color) { pos = pos + Point(1, 1); - draw_string_outline(canvas, pos, session_label); - canvas.draw_text(pos, default_font, session_label_color, session_label); + draw_string_outline(canvas, font, pos, session_label); + canvas.draw_text(pos, font, session_label_color, session_label); - pos = pos + Point(default_font.str_w(session_label) + LABEL_GAP, 0); + pos = pos + Point(font.string_width(session_label).decimal() + LABEL_GAP, 0); - draw_string_outline(canvas, pos, view_title); - canvas.draw_text(pos, default_font, view_title_color, view_title); + draw_string_outline(canvas, font, pos, view_title); + canvas.draw_text(pos, font, view_title_color, view_title); } } diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index 90646e55c7..dfc1dd985f 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -22,6 +22,7 @@ #include #include #include +#include /* local includes */ #include "types.h" @@ -40,16 +41,11 @@ namespace Nitpicker { } -/************************* - ** Font initialization ** - *************************/ +/********************************* + ** Font used for view labeling ** + *********************************/ -extern char _binary_default_tff_start; - -namespace Nitpicker { - - Text_painter::Font default_font(&_binary_default_tff_start); -} +extern char _binary_default_tff_start[]; /************************************ @@ -81,6 +77,7 @@ class Nitpicker::Root : public Root_component, Global_keys &_global_keys; Framebuffer::Mode _scr_mode { }; View_stack &_view_stack; + Font const &_font; User_state &_user_state; View_component &_pointer_origin; View_component &_builtin_background; @@ -109,7 +106,7 @@ class Nitpicker::Root : public Root_component, bool const provides_default_bg = (label == "backdrop"); Session_component *session = new (md_alloc()) - Session_component(_env, label, _view_stack, _user_state, + Session_component(_env, label, _view_stack, _font, _user_state, _pointer_origin, _builtin_background, _framebuffer, provides_default_bg, *md_alloc(), unused_quota, _focus_reporter, *this); @@ -146,7 +143,7 @@ class Nitpicker::Root : public Root_component, */ Root(Env &env, Attached_rom_dataspace const &config, Session_list &session_list, Domain_registry const &domain_registry, - Global_keys &global_keys, View_stack &view_stack, + Global_keys &global_keys, View_stack &view_stack, Font const &font, User_state &user_state, View_component &pointer_origin, View_component &builtin_background, Allocator &md_alloc, Framebuffer::Session &framebuffer, Reporter &focus_reporter, @@ -155,7 +152,7 @@ class Nitpicker::Root : public Root_component, Root_component(&env.ep().rpc_ep(), &md_alloc), _env(env), _config(config), _session_list(session_list), _domain_registry(domain_registry), _global_keys(global_keys), - _view_stack(view_stack), _user_state(user_state), + _view_stack(view_stack), _font(font), _user_state(user_state), _pointer_origin(pointer_origin), _builtin_background(builtin_background), _framebuffer(framebuffer), @@ -278,10 +275,14 @@ struct Nitpicker::Main : Focus_updater Constructible _focus_rom { }; - Root _root = { _env, _config_rom, _session_list, *_domain_registry, - _global_keys, _view_stack, _user_state, _pointer_origin, - _builtin_background, _sliced_heap, _framebuffer, - _focus_reporter, *this }; + Tff_font::Static_glyph_buffer<4096> _glyph_buffer { }; + + Tff_font const _font { _binary_default_tff_start, _glyph_buffer }; + + Root _root { _env, _config_rom, _session_list, *_domain_registry, + _global_keys, _view_stack, _font, _user_state, _pointer_origin, + _builtin_background, _sliced_heap, _framebuffer, + _focus_reporter, *this }; /** * Focus_updater interface @@ -350,7 +351,7 @@ struct Nitpicker::Main : Focus_updater */ void _draw_and_flush() { - _view_stack.draw(_fb_screen->screen).flush([&] (Rect const &rect) { + _view_stack.draw(_fb_screen->screen, _font).flush([&] (Rect const &rect) { _framebuffer.refresh(rect.x1(), rect.y1(), rect.w(), rect.h()); }); } @@ -446,7 +447,7 @@ void Nitpicker::Main::_handle_input() _view_stack.geometry(_pointer_origin, Rect(_user_state.pointer_pos(), Area())); /* perform redraw and flush pixels to the framebuffer */ - _view_stack.draw(_fb_screen->screen).flush([&] (Rect const &rect) { + _view_stack.draw(_fb_screen->screen, _font).flush([&] (Rect const &rect) { _framebuffer.refresh(rect.x1(), rect.y1(), rect.w(), rect.h()); }); diff --git a/repos/os/src/server/nitpicker/pointer_origin.h b/repos/os/src/server/nitpicker/pointer_origin.h index efca9a67f4..a3f0a642cc 100644 --- a/repos/os/src/server/nitpicker/pointer_origin.h +++ b/repos/os/src/server/nitpicker/pointer_origin.h @@ -35,7 +35,7 @@ struct Nitpicker::Pointer_origin : View_component int frame_size(Focus const &) const override { return 0; } void frame(Canvas_base &, Focus const &) const override { } - void draw(Canvas_base &, Focus const &) const override { } + void draw(Canvas_base &, Font const &, Focus const &) const override { } }; #endif /* _POINTER_ORIGIN_H_ */ diff --git a/repos/os/src/server/nitpicker/session_component.cc b/repos/os/src/server/nitpicker/session_component.cc index 947298cb1a..8fd0c62c41 100644 --- a/repos/os/src/server/nitpicker/session_component.cc +++ b/repos/os/src/server/nitpicker/session_component.cc @@ -167,7 +167,7 @@ void Session_component::_execute_command(Command const &command) Locked_ptr view(_view_handle_registry.lookup(cmd.view)); if (view.valid()) - _view_stack.title(*view, cmd.title.string()); + _view_stack.title(*view, _font, cmd.title.string()); return; } @@ -259,6 +259,7 @@ Session_component::View_handle Session_component::create_view(View_handle parent catch (Allocator::Out_of_memory) { throw Out_of_ram(); } } + view->title(_font, ""); view->apply_origin_policy(_pointer_origin); _view_list.insert(view); diff --git a/repos/os/src/server/nitpicker/session_component.h b/repos/os/src/server/nitpicker/session_component.h index 67f6184554..eb79faaf39 100644 --- a/repos/os/src/server/nitpicker/session_component.h +++ b/repos/os/src/server/nitpicker/session_component.h @@ -99,6 +99,8 @@ class Nitpicker::Session_component : public Rpc_object, View_stack &_view_stack; + Font const &_font; + Focus_controller &_focus_controller; Signal_context_capability _mode_sigh { }; @@ -166,6 +168,7 @@ class Nitpicker::Session_component : public Rpc_object, Session_component(Env &env, Session_label const &label, View_stack &view_stack, + Font const &font, Focus_controller &focus_controller, View_component &pointer_origin, View_component &builtin_background, @@ -181,7 +184,7 @@ class Nitpicker::Session_component : public Rpc_object, _session_alloc(&session_alloc, ram_quota), _framebuffer(framebuffer), _framebuffer_session_component(view_stack, *this, framebuffer, *this), - _view_stack(view_stack), _focus_controller(focus_controller), + _view_stack(view_stack), _font(font), _focus_controller(focus_controller), _pointer_origin(pointer_origin), _builtin_background(builtin_background), _framebuffer_session_cap(_env.ep().manage(_framebuffer_session_component)), diff --git a/repos/os/src/server/nitpicker/view_component.cc b/repos/os/src/server/nitpicker/view_component.cc index ab5bcd5572..189d626647 100644 --- a/repos/os/src/server/nitpicker/view_component.cc +++ b/repos/os/src/server/nitpicker/view_component.cc @@ -76,12 +76,12 @@ namespace Nitpicker { using namespace Nitpicker; -void View_component::title(Title const &title) +void View_component::title(Font const &font, Title const &title) { _title = title; /* calculate label size, the position is defined by the view stack */ - _label_rect = Rect(Point(0, 0), label_size(_owner.label().string(), + _label_rect = Rect(Point(0, 0), label_size(font, _owner.label().string(), _title.string())); } @@ -97,7 +97,7 @@ void View_component::frame(Canvas_base &canvas, Focus const &focus) const } -void View_component::draw(Canvas_base &canvas, Focus const &focus) const +void View_component::draw(Canvas_base &canvas, Font const &font, Focus const &focus) const { Texture_painter::Mode const op = texture_painter_mode(focus, _owner); @@ -138,7 +138,7 @@ void View_component::draw(Canvas_base &canvas, Focus const &focus) const /* draw label */ Color const frame_color = owner_color; - draw_label(canvas, _label_rect.p1(), _owner.label().string(), white(), + draw_label(canvas, font, _label_rect.p1(), _owner.label().string(), white(), _title.string(), frame_color); } diff --git a/repos/os/src/server/nitpicker/view_component.h b/repos/os/src/server/nitpicker/view_component.h index ce599306a2..d130cb8f55 100644 --- a/repos/os/src/server/nitpicker/view_component.h +++ b/repos/os/src/server/nitpicker/view_component.h @@ -96,10 +96,10 @@ class Nitpicker::View_component : private Same_buffer_list_elem, View_component *_parent; /* parent view */ Rect _geometry { }; /* position and size relative to parent */ - Rect _label_rect { }; /* position and size of label */ + Rect _label_rect { }; /* position and size of label */ Point _buffer_off { }; /* offset to the visible buffer area */ View_owner &_owner; - Title _title { }; + Title _title { "" }; Dirty_rect _dirty_rect { }; List _children { }; @@ -130,11 +130,8 @@ class Nitpicker::View_component : private Same_buffer_list_elem, View_component(View_owner &owner, Transparent transparent, Background bg, View_component *parent) : - _transparent(transparent), _background(bg), _parent(parent), - _owner(owner) - { - title(""); /* initialize '_label_rect' */ - } + _transparent(transparent), _background(bg), _parent(parent), _owner(owner) + { } virtual ~View_component() { @@ -217,12 +214,12 @@ class Nitpicker::View_component : private Same_buffer_list_elem, /** * Draw view on canvas */ - virtual void draw(Canvas_base &canvas, Focus const &) const; + virtual void draw(Canvas_base &, Font const &, Focus const &) const; /** * Set view title */ - void title(Title const &title); + void title(Font const &, Title const &); /** * Return successor in view stack diff --git a/repos/os/src/server/nitpicker/view_stack.cc b/repos/os/src/server/nitpicker/view_stack.cc index cd6ebb01e4..c8177d1cf4 100644 --- a/repos/os/src/server/nitpicker/view_stack.cc +++ b/repos/os/src/server/nitpicker/view_stack.cc @@ -168,7 +168,8 @@ void View_stack::_place_labels(Rect rect) } -void View_stack::draw_rec(Canvas_base &canvas, View_component const *view, Rect rect) const +void View_stack::draw_rec(Canvas_base &canvas, Font const &font, + View_component const *view, Rect rect) const { Rect clipped; @@ -185,8 +186,8 @@ void View_stack::draw_rec(Canvas_base &canvas, View_component const *view, Rect View_component const *next = _next_view(*view); /* draw areas at the top/left of the current view */ - if (next && top.valid()) draw_rec(canvas, next, top); - if (next && left.valid()) draw_rec(canvas, next, left); + if (next && top.valid()) draw_rec(canvas, font, next, top); + if (next && left.valid()) draw_rec(canvas, font, next, left); /* draw current view */ view->dirty_rect().flush([&] (Rect const &dirty_rect) { @@ -195,15 +196,15 @@ void View_stack::draw_rec(Canvas_base &canvas, View_component const *view, Rect /* draw background if view is transparent */ if (view->uses_alpha()) - draw_rec(canvas, _next_view(*view), clipped); + draw_rec(canvas, font, _next_view(*view), clipped); view->frame(canvas, _focus); - view->draw(canvas, _focus); + view->draw(canvas, font, _focus); }); /* draw areas at the bottom/right of the current view */ - if (next && right.valid()) draw_rec(canvas, next, right); - if (next && bottom.valid()) draw_rec(canvas, next, bottom); + if (next && right.valid()) draw_rec(canvas, font, next, right); + if (next && bottom.valid()) draw_rec(canvas, font, next, bottom); } @@ -285,9 +286,9 @@ void View_stack::stack(View_component &view, View_component const *neighbor, boo } -void View_stack::title(View_component &view, const char *title) +void View_stack::title(View_component &view, Font const &font, const char *title) { - view.title(title); + view.title(font, title); _place_labels(view.abs_geometry()); _mark_view_as_dirty(view, _outline(view)); diff --git a/repos/os/src/server/nitpicker/view_stack.h b/repos/os/src/server/nitpicker/view_stack.h index 47f8d60677..32e704a617 100644 --- a/repos/os/src/server/nitpicker/view_stack.h +++ b/repos/os/src/server/nitpicker/view_stack.h @@ -115,17 +115,17 @@ class Nitpicker::View_stack * * \param view current view in view stack */ - void draw_rec(Canvas_base &, View_component const *view, Rect) const; + void draw_rec(Canvas_base &, Font const &, View_component const *, Rect) const; /** * Draw dirty areas */ - Dirty_rect draw(Canvas_base &canvas) const + Dirty_rect draw(Canvas_base &canvas, Font const &font) const { Dirty_rect result = _dirty_rect; _dirty_rect.flush([&] (Rect const &rect) { - draw_rec(canvas, _first_view(), rect); }); + draw_rec(canvas, font, _first_view(), rect); }); return result; } @@ -227,7 +227,7 @@ class Nitpicker::View_stack /** * Set view title */ - void title(View_component &view, char const *title); + void title(View_component &view, Font const &font, char const *title); /** * Find view at specified position diff --git a/repos/ports/src/app/seoul/console.cc b/repos/ports/src/app/seoul/console.cc index c7fcadaac6..c5148c5cb1 100644 --- a/repos/ports/src/app/seoul/console.cc +++ b/repos/ports/src/app/seoul/console.cc @@ -24,7 +24,7 @@ #include /* nitpicker graphics backend */ -#include +#include #include #include @@ -32,8 +32,10 @@ /* local includes */ #include "console.h" -extern char _binary_mono_tff_start; -Text_painter::Font default_font(&_binary_mono_tff_start); +extern char _binary_mono_tff_start[]; + +static Tff_font::Static_glyph_buffer<4096> glyph_buffer { }; +static Tff_font default_font(_binary_mono_tff_start, glyph_buffer); static struct { Genode::uint64_t checksum1 = 0; @@ -241,7 +243,7 @@ unsigned Seoul::Console::_handle_fb() for (int j=0; j<25; j++) { for (int i=0; i<80; i++) { - Genode::Surface_base::Point where(i*8, j*15); + Text_painter::Position const where(i*8, j*15); char character = *((char *) (_guest_fb +(_regs->offset << 1) +j*80*2+i*2)); char colorvalue = *((char *) (_guest_fb+(_regs->offset << 1)+j*80*2+i*2+1)); char buffer[2]; buffer[0] = character; buffer[1] = 0;