os: reworked nitpicker_gfx/text_painter.h

This patch improves the `Text_painter` utility that is commonly used by
native Genode components to render text:

- Support for subpixel positioning
- Generic interface for accessing font data
- Basic UTF-8 support

Since the change decouples the font format from the 'Text_painter' and
changes the API to use the sub-pixel accurate 'Text_painter::Position'
type, all users of the utility require an adaptation.

Fixes #2716
This commit is contained in:
Norman Feske 2018-03-08 18:27:42 +01:00 committed by Christian Helmuth
parent 4c0f70fbcb
commit 3778558608
34 changed files with 733 additions and 341 deletions

View File

@ -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)

View File

@ -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);
}

View File

@ -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;

View File

@ -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());
}

View File

@ -14,6 +14,10 @@
#ifndef _STYLES_H_
#define _STYLES_H_
/* Genode includes */
#include <nitpicker_gfx/tff_font.h>
/* 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 (&section_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 { &section_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_ */

View File

@ -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 <typename PT> class Titlebar; }
static Scout::Font title_font(TITLE_TFF);
template <typename PT>
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);
}

View File

@ -26,8 +26,8 @@
/*
* Nitpicker's graphics backend
*/
#include <nitpicker_gfx/text_painter.h>
#include <nitpicker_gfx/box_painter.h>
#include <nitpicker_gfx/tff_font.h>
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<Pixel_rgb565> _canvas { _fb_ds.local_addr<Pixel_rgb565>(),
::Area(_win_w, _win_h) };
Log_window _log_window { _canvas };
Log_window _log_window { _canvas, _font };
void _init_canvas()
{

View File

@ -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)

View File

@ -11,6 +11,9 @@
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <nitpicker_gfx/tff_font.h>
/* 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;
}

View File

@ -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.

View File

@ -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_rgb888> &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());
}
};

View File

@ -14,6 +14,9 @@
#ifndef _STYLE_DATABASE_H_
#define _STYLE_DATABASE_H_
/* Genode includes */
#include <nitpicker_gfx/tff_font.h>
/* gems includes */
#include <gems/file.h>
#include <gems/png_image.h>
@ -55,8 +58,12 @@ class Menu_view::Style_database
struct Font_entry : List<Font_entry>::Element
{
String<PATH_MAX_LEN> 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<char>())
glyph_buffer(tff_file.data<char>(), alloc),
font(tff_file.data<char>(), glyph_buffer)
{ }
};

View File

@ -13,7 +13,7 @@
/* Genode includes */
#include <os/texture_rgb888.h>
#include <nitpicker_gfx/text_painter.h>
#include <nitpicker_gfx/tff_font.h>
#include <util/xml_node.h>
#include <decorator/xml_utils.h>
@ -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<char>());
static Tff_font::Allocated_glyph_buffer glyph_buffer(tff_file.data<char>(), alloc);
static Tff_font font(tff_file.data<char>(), 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);
}

View File

@ -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 <os/pixel_rgb565.h>
template <typename PT>
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_ */

View File

@ -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_ */

View File

@ -21,6 +21,7 @@
#include <base/attached_rom_dataspace.h>
#include <base/attached_ram_dataspace.h>
#include <input/event.h>
#include <nitpicker_gfx/tff_font.h>
/* terminal includes */
#include <terminal/decoder.h>
@ -52,7 +53,10 @@ struct Terminal::Main : Character_consumer
*/
static char const *_font_data(Xml_node config);
Reconstructible<Font> _font { _font_data(_config.xml()) };
Tff_font::Static_glyph_buffer<4096> _glyph_buffer { };
Reconstructible<Tff_font> _font { _font_data(_config.xml()), _glyph_buffer };
Reconstructible<Font_family> _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);
/*

View File

@ -22,10 +22,10 @@
/* nitpicker graphic back end */
#include <nitpicker_gfx/text_painter.h>
#include <nitpicker_gfx/box_painter.h>
/* 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 &regular_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<PT>();
Surface<PT> 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<PT>(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,

View File

@ -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 <util/noncopyable.h>
#include <base/stdint.h>
#include <os/surface.h>
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<Fixpoint_number> 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 <typename PT>
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_ */

View File

@ -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 <base/stdint.h>
#include <os/surface.h>
#include <util/interface.h>
#include <util/utf8.h>
#include <nitpicker_gfx/glyph_painter.h>
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 <typename FN>
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 <typename PT>
static inline void paint(Genode::Surface<PT> &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())));
}
};

View File

@ -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 <base/allocator.h>
#include <nitpicker_gfx/text_painter.h>
class Tff_font : public Text_painter::Font
{
public:
struct Glyph_buffer
{
char * const ptr;
Genode::size_t const size;
};
template <unsigned SIZE>
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_ */

View File

@ -261,7 +261,7 @@ puts $launchpad_config_fd {<config>
<launcher name="launchpad" ram_quota="6M" caps="1000">
<configfile name="launchpad.config" />
</launcher>
<launcher name="nitlog" ram_quota="1M" caps="50"/>
<launcher name="nitlog" ram_quota="1M" caps="70"/>
<launcher name="liquid_fb" ram_quota="7M" caps="70">
<config resize_handle="on" />
</launcher>

View File

@ -19,7 +19,7 @@
#include <os/pixel_rgb565.h>
#include <nitpicker_session/connection.h>
#include <nitpicker_gfx/box_painter.h>
#include <nitpicker_gfx/text_painter.h>
#include <nitpicker_gfx/tff_font.h>
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 <typename PT>
@ -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);

View File

@ -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);

View File

@ -24,6 +24,8 @@
namespace Nitpicker {
struct Canvas_base;
template <typename PT> 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);
}
};

View File

@ -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);
}
}

View File

@ -22,6 +22,7 @@
#include <input_session/connection.h>
#include <framebuffer_session/connection.h>
#include <os/session_policy.h>
#include <nitpicker_gfx/tff_font.h>
/* 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<Session_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<Session_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<Session_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<Session_component>,
Root_component<Session_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<Attached_rom_dataspace> _focus_rom { };
Root<PT> _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<PT> _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()); });

View File

@ -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_ */

View File

@ -167,7 +167,7 @@ void Session_component::_execute_command(Command const &command)
Locked_ptr<View_component> 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);

View File

@ -99,6 +99,8 @@ class Nitpicker::Session_component : public Rpc_object<Session>,
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>,
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>,
_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)),

View File

@ -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);
}

View File

@ -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<View_parent_elem> _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

View File

@ -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));

View File

@ -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

View File

@ -24,7 +24,7 @@
#include <util/register.h>
/* nitpicker graphics backend */
#include <nitpicker_gfx/text_painter.h>
#include <nitpicker_gfx/tff_font.h>
#include <nul/motherboard.h>
#include <host/screen.h>
@ -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;