Index: uspace/lib/draw/Makefile
===================================================================
--- uspace/lib/draw/Makefile	(revision 071fefec5f0bb65ab129bc513b289e3e9d6700df)
+++ uspace/lib/draw/Makefile	(revision 2cc1ec062d6e172ce570169e6b0485b9da3db610)
@@ -37,4 +37,5 @@
 	cursor/embedded.c \
 	font/embedded.c \
+	font/bitmap_backend.c \
 	gfx/font-8x16.c \
 	gfx/cursor-11x18.c \
Index: uspace/lib/draw/font.c
===================================================================
--- uspace/lib/draw/font.c	(revision 071fefec5f0bb65ab129bc513b289e3e9d6700df)
+++ uspace/lib/draw/font.c	(revision 2cc1ec062d6e172ce570169e6b0485b9da3db610)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2012 Petr Koupy
+ * Copyright (c) 2014 Martin Sucha
  * All rights reserved.
  *
@@ -34,6 +35,7 @@
  */
 
-#include <assert.h>
 #include <malloc.h>
+#include <errno.h>
+#include <str.h>
 
 #include "font.h"
@@ -41,127 +43,129 @@
 #include "drawctx.h"
 
-void font_init(font_t *font, font_decoder_type_t decoder, char *path, uint16_t points)
+font_t *font_create(font_backend_t *backend, void *backend_data)
 {
-	font->points = points;
-
-	switch (decoder) {
-	case FONT_DECODER_EMBEDDED:
-		font->decoder = &fd_embedded;
-		break;
-	default:
-		font->decoder = NULL;
-		break;
-	}
-
-	if (font->decoder) {
-		font->decoder->init(path, &font->glyph_count, &font->decoder_data);
-
-		if (font->glyph_count > 0) {
-			font->glyphs = (surface_t **) malloc(sizeof(surface_t *) * font->glyph_count);
-		} else {
-			font->glyphs = NULL;
-		}
-
-		if (font->glyphs) {
-			for (size_t i = 0; i < font->glyph_count; ++i) {
-				font->glyphs[i] = NULL;
-			}
-		} else {
-			font->glyph_count = 0;
-		}
-	} else {
-		font->glyph_count = 0;
-		font->glyphs = NULL;
-		font->decoder_data = NULL;
-	}
+	font_t *font = malloc(sizeof(font_t));
+	if (font == NULL)
+		return NULL;
+	
+	font->backend = backend;
+	font->backend_data = backend_data;
+	
+	return font;
 }
 
 void font_release(font_t *font)
 {
-	if (font->glyphs) {
-		for (size_t i = 0; i < font->glyph_count; ++i) {
-			if (font->glyphs[i]) {
-				surface_destroy(font->glyphs[i]);
+	font->backend->release(font->backend_data);
+}
+
+int font_get_metrics(font_t *font, font_metrics_t *metrics) {
+	return font->backend->get_font_metrics(font->backend_data, metrics);
+}
+
+int font_resolve_glyph(font_t *font, wchar_t c, glyph_id_t *glyph_id) {
+	return font->backend->resolve_glyph(font->backend_data, c, glyph_id);
+}
+
+int font_get_glyph_metrics(font_t *font, glyph_id_t glyph_id,
+    glyph_metrics_t *glyph_metrics)
+{
+	return font->backend->get_glyph_metrics(font->backend_data,
+	    glyph_id, glyph_metrics);
+}
+
+int font_render_glyph(font_t *font, drawctx_t *context, source_t *source,
+    sysarg_t x, sysarg_t y, glyph_id_t glyph_id)
+{
+	return font->backend->render_glyph(font->backend_data, context, source,
+	    x, y, glyph_id);
+}
+
+/* TODO this is bad interface */
+int font_get_box(font_t *font, char *text, sysarg_t *width, sysarg_t *height)
+{
+	font_metrics_t fm;
+	int rc = font_get_metrics(font, &fm);
+	if (rc != EOK)
+		return rc;
+
+	native_t x = 0;
+
+	size_t off = 0;
+	while (true) {
+		wchar_t c = str_decode(text, &off, STR_NO_LIMIT);
+		if (c == 0)
+			break;
+		
+		glyph_id_t glyph_id;
+		rc = font_resolve_glyph(font, c, &glyph_id);
+		if (rc != EOK) {
+			int rc2 = font_resolve_glyph(font, U_SPECIAL, &glyph_id);
+			if (rc2 != EOK) {
+				return rc;
 			}
 		}
-		free(font->glyphs);
+		
+		glyph_metrics_t glyph_metrics;
+		rc = font_get_glyph_metrics(font, glyph_id, &glyph_metrics);
+		if (rc != EOK)
+			return rc;
+		
+		x += glyph_metrics_get_advancement(&glyph_metrics);
 	}
-	
-	if (font->decoder) {
-		font->decoder->release(font->decoder_data);
-	}
+
+	*width = x;
+	*height = fm.ascender + fm.descender;
+	return EOK;
 }
 
-void font_get_box(font_t *font, char *text, sysarg_t *width, sysarg_t *height)
+/* TODO this is bad interface */
+int font_draw_text(font_t *font, drawctx_t *context, source_t *source,
+    const char *text, sysarg_t sx, sysarg_t sy)
 {
-	assert(width);
-	assert(height);
-
-	(*width) = 0;
-	(*height) = 0;
-
-	if (!text) {
-		return;
-	}
-
-	while (*text) {
-		uint16_t glyph_idx = font->decoder->resolve(*text, font->decoder_data);
-		if (glyph_idx < font->glyph_count) {
-			if (!font->glyphs[glyph_idx]) {
-				font->glyphs[glyph_idx] =
-				    font->decoder->render(glyph_idx, font->points);
-			}
-
-			surface_t *glyph = font->glyphs[glyph_idx];
-			if (glyph) {
-				sysarg_t w;
-				sysarg_t h;
-				surface_get_resolution(glyph, &w, &h);
-				(*width) += w;
-				(*height) = (*height) < h ? h : (*height);
-			}
-		}
-		++text;
-	}
-}
-
-void font_draw_text(font_t *font, drawctx_t *context, source_t *source,
-    const char *text, sysarg_t x, sysarg_t y)
-{
-	assert(context);
-	assert(source);
-
 	drawctx_save(context);
 	drawctx_set_compose(context, compose_over);
 
-	while (*text) {
-		uint16_t glyph_idx = font->decoder->resolve(*text, font->decoder_data);
-		if (glyph_idx < font->glyph_count) {
-			if (!font->glyphs[glyph_idx]) {
-				font->glyphs[glyph_idx] =
-				    font->decoder->render(glyph_idx, font->points);
-			}
+	font_metrics_t fm;
+	int rc = font_get_metrics(font, &fm);
+	if (rc != EOK)
+		return rc;
 
-			surface_t *glyph = font->glyphs[glyph_idx];
-			if (glyph) {
-				sysarg_t w;
-				sysarg_t h;
-				surface_get_resolution(glyph, &w, &h);
+	native_t baseline = sy + fm.ascender;
+	native_t x = sx;
 
-				transform_t transform;
-				transform_identity(&transform);
-				transform_translate(&transform, x, y);
-				source_set_transform(source, transform);
-				source_set_mask(source, glyph, false);
-				drawctx_transfer(context, x, y, w, h);
-
-				x += w;
+	size_t off = 0;
+	while (true) {
+		wchar_t c = str_decode(text, &off, STR_NO_LIMIT);
+		if (c == 0)
+			break;
+		
+		glyph_id_t glyph_id;
+		rc = font_resolve_glyph(font, c, &glyph_id);
+		if (rc != EOK) {
+			int rc2 = font_resolve_glyph(font, U_SPECIAL, &glyph_id);
+			if (rc2 != EOK) {
+				return rc;
 			}
 		}
-		++text;
+		
+		glyph_metrics_t glyph_metrics;
+		rc = font_get_glyph_metrics(font, glyph_id, &glyph_metrics);
+		if (rc != EOK)
+			return rc;
+
+		rc = font_render_glyph(font, context, source, x, baseline,
+		    glyph_id);
+		if (rc != EOK)
+			return rc;
+
+		x += glyph_metrics_get_advancement(&glyph_metrics);
+
 	}
 
 	drawctx_restore(context);
 	source_set_mask(source, NULL, false);
+
+	return EOK;
 }
 
Index: uspace/lib/draw/font.h
===================================================================
--- uspace/lib/draw/font.h	(revision 071fefec5f0bb65ab129bc513b289e3e9d6700df)
+++ uspace/lib/draw/font.h	(revision 2cc1ec062d6e172ce570169e6b0485b9da3db610)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2012 Petr Koupy
+ * Copyright (c) 2014 Martin Sucha
  * All rights reserved.
  *
@@ -45,28 +46,72 @@
 typedef struct drawctx drawctx_t;
 
-typedef enum {
-	FONT_DECODER_EMBEDDED
-} font_decoder_type_t;
+typedef int metric_t;
 
 typedef struct {
-	void (*init)(char *, uint16_t *, void **);
-	uint16_t (*resolve)(const wchar_t, void *);
-	surface_t *(*render)(uint16_t, uint16_t);
+	/* Horizontal distance between origin and left side of the glyph */ 
+	metric_t left_side_bearing;
+	
+	/* Width of the actual glyph drawn */
+	metric_t width;
+	
+	/* Horizontal distance between right side of the glyph and origin
+	   of the next glyph */
+	metric_t right_side_bearing;
+	
+	/* Vertical distance between baseline and top of the glyph
+	   (positive to top) */
+	metric_t ascender;
+	
+	/* Height of the actual glyph drawn */
+	metric_t height;
+} glyph_metrics_t;
+
+static inline metric_t glyph_metrics_get_descender(glyph_metrics_t *gm)
+{
+	return gm->height - gm->ascender;
+}
+
+static inline metric_t glyph_metrics_get_advancement(glyph_metrics_t *gm)
+{
+	return gm->left_side_bearing + gm->width + gm->right_side_bearing;
+}
+
+typedef struct {
+	/* Distance between top of the line and baseline */
+	metric_t ascender;
+	
+	/* Distance between baseline and bottom of the line */
+	metric_t descender;
+	
+	/* Distance between bottom of the line and top of the next line */
+	metric_t leading;
+} font_metrics_t;
+
+typedef uint32_t glyph_id_t;
+
+typedef struct {
+	int (*get_font_metrics)(void *, font_metrics_t *);
+	int (*resolve_glyph)(void *, wchar_t, glyph_id_t *);
+	int (*get_glyph_metrics)(void *, glyph_id_t, glyph_metrics_t *);
+	int (*render_glyph)(void *, drawctx_t *, source_t *, sysarg_t,
+	    sysarg_t, glyph_id_t);
 	void (*release)(void *);
-} font_decoder_t;
+} font_backend_t;
 
-typedef struct font {
-	uint16_t points;
-	uint16_t glyph_count;
-	surface_t **glyphs;
-	font_decoder_t *decoder;
-	void *decoder_data;
+typedef struct {
+	font_backend_t *backend;
+	void *backend_data;
 } font_t;
 
-extern void font_init(font_t *, font_decoder_type_t, char *, uint16_t);
+extern font_t *font_create(font_backend_t *, void *);
+extern int font_get_metrics(font_t *, font_metrics_t *);
+extern int font_resolve_glyph(font_t *, wchar_t, glyph_id_t *);
+extern int font_get_glyph_metrics(font_t *, glyph_id_t, glyph_metrics_t *);
+extern int font_render_glyph(font_t *, drawctx_t *, source_t *,
+    sysarg_t, sysarg_t, glyph_id_t);
 extern void font_release(font_t *);
 
-extern void font_get_box(font_t *, char *, sysarg_t *, sysarg_t *);
-extern void font_draw_text(font_t *, drawctx_t *, source_t *, const char *,
+extern int font_get_box(font_t *, char *, sysarg_t *, sysarg_t *);
+extern int font_draw_text(font_t *, drawctx_t *, source_t *, const char *,
     sysarg_t, sysarg_t);
 
Index: uspace/lib/draw/font/bitmap_backend.c
===================================================================
--- uspace/lib/draw/font/bitmap_backend.c	(revision 2cc1ec062d6e172ce570169e6b0485b9da3db610)
+++ uspace/lib/draw/font/bitmap_backend.c	(revision 2cc1ec062d6e172ce570169e6b0485b9da3db610)
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * Copyright (c) 2014 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <malloc.h>
+#include <errno.h>
+
+#include "../font.h"
+#include "../drawctx.h"
+#include "bitmap_backend.h"
+
+typedef struct {
+	surface_t *surface;
+	glyph_metrics_t metrics;
+	bool metrics_loaded;
+} glyph_cache_item_t;
+
+typedef struct {
+	uint16_t points;
+	uint32_t glyph_count;
+	font_metrics_t font_metrics;
+	glyph_cache_item_t *glyph_cache;
+	bitmap_font_decoder_t *decoder;
+	void *decoder_data;
+	bool scale;
+	double scale_ratio;
+} bitmap_backend_data_t;
+
+static int bb_get_font_metrics(void *backend_data, font_metrics_t *font_metrics)
+{
+	bitmap_backend_data_t *data = (bitmap_backend_data_t *) backend_data;
+	
+	*font_metrics = data->font_metrics;
+	
+	return EOK;
+}
+
+static int bb_resolve_glyph(void *backend_data, wchar_t c, glyph_id_t *glyph_id)
+{
+	bitmap_backend_data_t *data = (bitmap_backend_data_t *) backend_data;
+	return data->decoder->resolve_glyph(data->decoder_data, c, glyph_id);
+}
+
+static int bb_get_glyph_metrics(void *backend_data, glyph_id_t glyph_id,
+    glyph_metrics_t *glyph_metrics)
+{
+	bitmap_backend_data_t *data = (bitmap_backend_data_t *) backend_data;
+	
+	if (glyph_id >= data->glyph_count)
+		return ENOENT;
+	
+	if (data->glyph_cache[glyph_id].metrics_loaded) {
+		*glyph_metrics = data->glyph_cache[glyph_id].metrics;
+		return EOK;
+	}
+	
+	glyph_metrics_t gm;
+	
+	int rc = data->decoder->load_glyph_metrics(data->decoder_data, glyph_id,
+	    &gm);
+	if (rc != EOK)
+		return rc;
+	
+	if (data->scale) {
+		gm.left_side_bearing = (metric_t)
+		    (data->scale_ratio * gm.left_side_bearing + 0.5);
+		gm.width = (metric_t)
+		    (data->scale_ratio * gm.width + 0.5);
+		gm.right_side_bearing = (metric_t)
+		    (data->scale_ratio * gm.right_side_bearing + 0.5);
+		gm.ascender = (metric_t)
+		    (data->scale_ratio * gm.ascender + 0.5);
+		gm.height = (metric_t)
+		    (data->scale_ratio * gm.height + 0.5);
+	}
+	
+	
+	
+	data->glyph_cache[glyph_id].metrics = gm;
+	data->glyph_cache[glyph_id].metrics_loaded = true;
+	*glyph_metrics = gm;
+	return EOK;
+}
+
+static int get_glyph_surface(bitmap_backend_data_t *data, glyph_id_t glyph_id,
+    surface_t **result)
+{
+	if (glyph_id >= data->glyph_count)
+		return ENOENT;
+	
+	if (data->glyph_cache[glyph_id].surface != NULL) {
+		*result = data->glyph_cache[glyph_id].surface;
+		return EOK;
+	}
+	
+	surface_t *raw_surface;
+	int rc = data->decoder->load_glyph_surface(data->decoder_data, glyph_id,
+	    &raw_surface);
+	if (rc != EOK)
+		return rc;
+	
+	sysarg_t w;
+	sysarg_t h;
+	surface_get_resolution(raw_surface, &w, &h);
+	
+	if (h == data->points) {
+		*result = raw_surface;
+		return EOK;
+	}
+	
+	source_t source;
+	source_init(&source);
+	source_set_texture(&source, raw_surface, false);
+
+	transform_t transform;
+	transform_identity(&transform);
+	double ratio = ((double) data->points) / ((double) h);
+	transform_scale(&transform, ratio, ratio);
+	source_set_transform(&source, transform);
+
+	double width = w;
+	double height = h;
+	transform_apply_linear(&transform, &width, &height);
+	surface_t *scaled_surface =
+	    surface_create((sysarg_t) (width + 0.5), (sysarg_t) (height + 0.5), NULL, 0);
+	if (!scaled_surface) {
+		surface_destroy(raw_surface);
+		return ENOMEM;
+	}
+
+	drawctx_t context;
+	drawctx_init(&context, scaled_surface);
+	drawctx_set_source(&context, &source);
+	drawctx_transfer(&context, 0, 0,
+	    (sysarg_t) (width + 0.5), (sysarg_t) (height + 0.5));
+
+	surface_destroy(raw_surface);
+	
+	data->glyph_cache[glyph_id].surface = scaled_surface;
+	*result = scaled_surface;
+	return EOK;
+}
+
+static int bb_render_glyph(void *backend_data, drawctx_t *context,
+    source_t *source, sysarg_t ox, sysarg_t oy, glyph_id_t glyph_id)
+{
+	bitmap_backend_data_t *data = (bitmap_backend_data_t *) backend_data;
+	
+	glyph_metrics_t glyph_metrics;
+	int rc = bb_get_glyph_metrics(backend_data, glyph_id, &glyph_metrics);
+	if (rc != EOK)
+		return rc;
+	
+	surface_t *glyph_surface;
+	rc = get_glyph_surface(data, glyph_id, &glyph_surface);
+	if (rc != EOK)
+		return rc;
+	
+	native_t x = ox + glyph_metrics.left_side_bearing;
+	native_t y = oy - glyph_metrics.ascender;
+	
+	transform_t transform;
+	transform_identity(&transform);
+	transform_translate(&transform, x, y);
+	source_set_transform(source, transform);
+	source_set_mask(source, glyph_surface, false);
+	drawctx_transfer(context, x, y, glyph_metrics.width,
+	    glyph_metrics.height);
+
+	return EOK;
+}
+
+static void bb_release(void *backend_data)
+{
+	bitmap_backend_data_t *data = (bitmap_backend_data_t *) backend_data;
+
+	for (size_t i = 0; i < data->glyph_count; ++i) {
+		if (data->glyph_cache[i].surface) {
+			surface_destroy(data->glyph_cache[i].surface);
+		}
+	}
+	free(data->glyph_cache);
+
+	data->decoder->release(data->decoder_data);
+}
+
+font_backend_t bitmap_backend = {
+	.get_font_metrics = bb_get_font_metrics,
+	.resolve_glyph = bb_resolve_glyph,
+	.get_glyph_metrics = bb_get_glyph_metrics,
+	.render_glyph = bb_render_glyph,
+	.release = bb_release
+};
+
+int bitmap_font_create(bitmap_font_decoder_t *decoder, void *decoder_data,
+    uint32_t glyph_count, font_metrics_t font_metrics, uint16_t points,
+    font_t **out_font)
+{
+	if (glyph_count == 0)
+		return EINVAL;
+	
+	bitmap_backend_data_t *data = malloc(sizeof(bitmap_backend_data_t));
+	if (data == NULL)
+		return ENOMEM;
+
+	data->glyph_count = glyph_count;
+	data->points = points;
+	data->decoder = decoder;
+	data->decoder_data = decoder_data;
+	data->font_metrics = font_metrics;
+	metric_t line_height = (font_metrics.ascender + font_metrics.descender);
+	if (points == line_height) {
+		data->scale = false;
+		data->scale_ratio = 1.0;
+	}
+	else {
+		data->scale = true;
+		data->scale_ratio = ((double) points) / ((double) line_height);
+		data->font_metrics.ascender = (metric_t)
+		    (data->scale_ratio * data->font_metrics.ascender + 0.5);
+		data->font_metrics.descender = (metric_t)
+		    (data->scale_ratio * data->font_metrics.descender - 0.5);
+		data->font_metrics.leading = (metric_t)
+		    (data->scale_ratio * data->font_metrics.leading + 0.5);
+	}
+
+	data->glyph_cache = calloc(data->glyph_count,
+	    sizeof(glyph_cache_item_t));
+	if (data->glyph_cache == NULL) {
+		free(data);
+		return ENOMEM;
+	}
+
+	for (size_t i = 0; i < data->glyph_count; ++i) {
+		data->glyph_cache[i].surface = NULL;
+		data->glyph_cache[i].metrics_loaded = false;
+	}
+
+	font_t *font = font_create(&bitmap_backend, data);
+	if (font == NULL) {
+		free(data->glyph_cache);
+		free(data);
+		return ENOMEM;
+	}
+	
+	*out_font = font;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/draw/font/bitmap_backend.h
===================================================================
--- uspace/lib/draw/font/bitmap_backend.h	(revision 2cc1ec062d6e172ce570169e6b0485b9da3db610)
+++ uspace/lib/draw/font/bitmap_backend.h	(revision 2cc1ec062d6e172ce570169e6b0485b9da3db610)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * Copyright (c) 2014 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef DRAW_FONT_BITMAP_BACKEND_H_
+#define DRAW_FONT_BITMAP_BACKEND_H_
+
+#include <sys/types.h>
+
+#include "../font.h"
+#include "../surface.h"
+#include "../source.h"
+
+typedef struct {
+	int (*resolve_glyph)(void *, const wchar_t, glyph_id_t *);
+	int (*load_glyph_surface)(void *, glyph_id_t, surface_t **);
+	int (*load_glyph_metrics)(void *, glyph_id_t, glyph_metrics_t *);
+	void (*release)(void *);
+} bitmap_font_decoder_t;
+
+extern int bitmap_font_create(bitmap_font_decoder_t *, void *, uint32_t,
+    font_metrics_t, uint16_t, font_t **);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/font/embedded.c
===================================================================
--- uspace/lib/draw/font/embedded.c	(revision 071fefec5f0bb65ab129bc513b289e3e9d6700df)
+++ uspace/lib/draw/font/embedded.c	(revision 2cc1ec062d6e172ce570169e6b0485b9da3db610)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2012 Petr Koupy
+ * Copyright (c) 2014 Martin Sucha
  * All rights reserved.
  *
@@ -34,71 +35,55 @@
  */
 
-#include <assert.h>
 #include <sys/types.h>
 #include <malloc.h>
+#include <errno.h>
 
 #include "../gfx/font-8x16.h"
 #include "embedded.h"
 #include "../drawctx.h"
+#include "bitmap_backend.h"
 
-static void fde_init(char *path, uint16_t *glyph_count, void **data)
+static int fde_resolve_glyph(void *unused, const wchar_t chr,
+    glyph_id_t *glyph_id)
 {
-	assert(glyph_count);
-	assert(data);
-
-	(*glyph_count) = FONT_GLYPHS;
-	(*data) = NULL;
+	bool found = false;
+	uint16_t glyph = fb_font_glyph(chr, &found);
+	if (!found)
+		return ENOENT;
+	
+	*glyph_id = glyph;
+	return EOK;
 }
 
-static uint16_t fde_resolve(const wchar_t chr, void *data)
+static int fde_load_glyph_surface(void *unused, glyph_id_t glyph_id,
+    surface_t **out_surface)
 {
-	return fb_font_glyph(chr);
+	surface_t *surface = surface_create(FONT_WIDTH, FONT_SCANLINES, NULL, 0);
+	if (!surface)
+		return ENOMEM;
+	
+	for (unsigned int y = 0; y < FONT_SCANLINES; ++y) {
+		for (unsigned int x = 0; x < FONT_WIDTH; ++x) {
+			pixel_t p = (fb_font[glyph_id][y] & (1 << (7 - x))) ? 
+			    PIXEL(255, 0, 0, 0) : PIXEL(0, 0, 0, 0);
+			surface_put_pixel(surface, x, y, p);
+		}
+	}
+	
+	*out_surface = surface;
+	return EOK;
 }
 
-static surface_t *fde_render(uint16_t glyph, uint16_t points)
+static int fde_load_glyph_metrics(void *unused, glyph_id_t glyph_id,
+    glyph_metrics_t *gm)
 {
-	surface_t *template = surface_create(FONT_WIDTH, FONT_SCANLINES, NULL, 0);
-	if (!template) {
-		return NULL;
-	}
-	for (unsigned int y = 0; y < FONT_SCANLINES; ++y) {
-		for (unsigned int x = 0; x < FONT_WIDTH; ++x) {
-			pixel_t p = (fb_font[glyph][y] & (1 << (7 - x))) ? 
-			    PIXEL(255, 0, 0, 0) : PIXEL(0, 0, 0, 0);
-			surface_put_pixel(template, x, y, p);
-		}
-	}
-
-	source_t source;
-	source_init(&source);
-	source_set_texture(&source, template, false);
-
-	transform_t transform;
-	transform_identity(&transform);
-	if (points != FONT_SCANLINES) {
-		double ratio = ((double) points) / ((double) FONT_SCANLINES);
-		transform_scale(&transform, ratio, ratio);
-		source_set_transform(&source, transform);
-	}
-
-	double width = FONT_WIDTH;
-	double height = FONT_SCANLINES;
-	transform_apply_linear(&transform, &width, &height);
-	surface_t *result =
-	    surface_create((sysarg_t) (width + 0.5), (sysarg_t) (height + 0.5), NULL, 0);
-	if (!result) {
-		surface_destroy(template);
-		return NULL;
-	}
-
-	drawctx_t context;
-	drawctx_init(&context, result);
-	drawctx_set_source(&context, &source);
-	drawctx_transfer(&context, 0, 0,
-	    (sysarg_t) (width + 0.5), (sysarg_t) (height + 0.5));
-
-	surface_destroy(template);
-
-	return result;
+	/* This is simple monospaced font, so fill this data statically */
+	gm->left_side_bearing = 0;
+	gm->width = FONT_WIDTH;
+	gm->right_side_bearing = 0;
+	gm->ascender = FONT_ASCENDER;
+	gm->height = FONT_SCANLINES;
+	
+	return EOK;
 }
 
@@ -108,11 +93,23 @@
 }
 
-font_decoder_t fd_embedded = {
-	.init = fde_init,
-	.resolve = fde_resolve,
-	.render = fde_render,
+bitmap_font_decoder_t fd_embedded = {
+	.resolve_glyph = fde_resolve_glyph,
+	.load_glyph_surface = fde_load_glyph_surface,
+	.load_glyph_metrics = fde_load_glyph_metrics,
 	.release = fde_release
 };
 
+font_metrics_t font_metrics = {
+	.ascender = FONT_ASCENDER,
+	.descender = (FONT_SCANLINES - FONT_ASCENDER),
+	.leading = 0
+};
+
+int embedded_font_create(font_t **font, uint16_t points)
+{
+	return bitmap_font_create(&fd_embedded, NULL, FONT_GLYPHS, font_metrics,
+	    points, font);
+}
+
 /** @}
  */
Index: uspace/lib/draw/font/embedded.h
===================================================================
--- uspace/lib/draw/font/embedded.h	(revision 071fefec5f0bb65ab129bc513b289e3e9d6700df)
+++ uspace/lib/draw/font/embedded.h	(revision 2cc1ec062d6e172ce570169e6b0485b9da3db610)
@@ -39,5 +39,5 @@
 #include "../font.h"
 
-extern font_decoder_t fd_embedded;
+extern int embedded_font_create(font_t **, uint16_t points);
 
 #endif
Index: uspace/lib/draw/gfx/font-8x16.c
===================================================================
--- uspace/lib/draw/gfx/font-8x16.c	(revision 071fefec5f0bb65ab129bc513b289e3e9d6700df)
+++ uspace/lib/draw/gfx/font-8x16.c	(revision 2cc1ec062d6e172ce570169e6b0485b9da3db610)
@@ -44,7 +44,12 @@
  * mark glyph if no specific glyph exists.
  *
+ * If found is not null, indicate whether the glyph was found or not.
+ *
  */
-uint16_t fb_font_glyph(const wchar_t ch)
+uint16_t fb_font_glyph(const wchar_t ch, bool *found)
 {
+	if (found)
+		*found = true;
+	
 	if (ch == 0x0000)
 		return 0;
@@ -361,4 +366,7 @@
 	if (ch == 0xfeff)
 		return 2896;
+	
+	if (found)
+		*found = false;
 	
 	return 2898;
Index: uspace/lib/draw/gfx/font-8x16.h
===================================================================
--- uspace/lib/draw/gfx/font-8x16.h	(revision 071fefec5f0bb65ab129bc513b289e3e9d6700df)
+++ uspace/lib/draw/gfx/font-8x16.h	(revision 2cc1ec062d6e172ce570169e6b0485b9da3db610)
@@ -37,10 +37,12 @@
 
 #include <sys/types.h>
+#include <stdbool.h>
 
 #define FONT_GLYPHS     2899
 #define FONT_WIDTH      8
 #define FONT_SCANLINES  16
+#define FONT_ASCENDER   12
 
-extern uint16_t fb_font_glyph(const wchar_t);
+extern uint16_t fb_font_glyph(const wchar_t, bool *);
 extern uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES];
 
