Index: uspace/lib/gfxfont/private/font.h
===================================================================
--- uspace/lib/gfxfont/private/font.h	(revision 5592c56bec345742686b5b607eadcd91d62d61de)
+++ uspace/lib/gfxfont/private/font.h	(revision d2100e23b019a7ed116b6d3d17c17625196dc4f7)
@@ -39,4 +39,6 @@
 
 #include <adt/list.h>
+#include <errno.h>
+#include <types/gfx/bitmap.h>
 #include <types/gfx/context.h>
 #include <types/gfx/font.h>
@@ -45,4 +47,10 @@
  *
  * This is private to libgfxfont.
+ *
+ * Font bitmap contains all the glyphs packed side by side (in order of
+ * @c gfx_font_t.glyphs). This is to conserve space and number of bitmaps
+ * used. The baselines of the glyphs are not mutually aligned.
+ * For each glyph @c gfx_glyph_t.origin designates
+ * pen start point (and thus the position of the baseline).
  */
 struct gfx_font {
@@ -53,5 +61,12 @@
 	/** Glyphs */
 	list_t glyphs;
+	/** Font bitmap */
+	gfx_bitmap_t *bitmap;
+	/** Bitmap rectangle */
+	gfx_rect_t rect;
 };
+
+extern errno_t gfx_font_splice_at_glyph(gfx_font_t *, gfx_glyph_t *,
+    gfx_coord_t, gfx_coord_t);
 
 #endif
Index: uspace/lib/gfxfont/private/glyph.h
===================================================================
--- uspace/lib/gfxfont/private/glyph.h	(revision 5592c56bec345742686b5b607eadcd91d62d61de)
+++ uspace/lib/gfxfont/private/glyph.h	(revision d2100e23b019a7ed116b6d3d17c17625196dc4f7)
@@ -39,4 +39,5 @@
 
 #include <adt/list.h>
+#include <gfx/coord.h>
 #include <types/gfx/glyph.h>
 
@@ -54,4 +55,8 @@
 	/** Text patterns (of gfx_glyph_pattern_t) */
 	list_t patterns;
+	/** Rectangle within font bitmap containing the glyph */
+	gfx_rect_t rect;
+	/** Glyph origin within font bitmap (pen start point) */
+	gfx_coord2_t origin;
 };
 
@@ -69,4 +74,7 @@
 };
 
+extern errno_t gfx_glyph_transfer(gfx_glyph_t *, gfx_coord_t, gfx_bitmap_t *,
+    gfx_rect_t *);
+
 #endif
 
Index: uspace/lib/gfxfont/src/font.c
===================================================================
--- uspace/lib/gfxfont/src/font.c	(revision 5592c56bec345742686b5b607eadcd91d62d61de)
+++ uspace/lib/gfxfont/src/font.c	(revision d2100e23b019a7ed116b6d3d17c17625196dc4f7)
@@ -37,4 +37,5 @@
 #include <assert.h>
 #include <errno.h>
+#include <gfx/bitmap.h>
 #include <gfx/font.h>
 #include <gfx/glyph.h>
@@ -70,4 +71,5 @@
 {
 	gfx_font_t *font;
+	gfx_bitmap_params_t params;
 	errno_t rc;
 
@@ -81,4 +83,14 @@
 	if (rc != EOK) {
 		assert(rc == EINVAL);
+		free(font);
+		return rc;
+	}
+
+	/* Create font bitmap */
+	gfx_bitmap_params_init(&params);
+	params.rect = font->rect;
+
+	rc = gfx_bitmap_create(font->gc, &params, NULL, &font->bitmap);
+	if (rc != EOK) {
 		free(font);
 		return rc;
@@ -190,4 +202,83 @@
 }
 
+/** Replace glyph graphic with empty space of specified width.
+ *
+ * This is used to resize a glyph in the font bitmap. This changes
+ * the bitmap widht and might also make the bitmap taller.
+ * Width and height of the glyph is also adjusted accordingly.
+ *
+ * @param font Font
+ * @param glyph Glyph to replace
+ * @param width Width of replacement space
+ * @param height Height of replacement space
+ */
+errno_t gfx_font_splice_at_glyph(gfx_font_t *font, gfx_glyph_t *glyph,
+    gfx_coord_t width, gfx_coord_t height)
+{
+	gfx_glyph_t *g;
+	gfx_bitmap_t *nbitmap;
+	gfx_bitmap_params_t params;
+	gfx_coord_t dwidth;
+	errno_t rc;
+
+	/* Change of width of glyph */
+	dwidth = width - (glyph->rect.p1.x - glyph->rect.p0.x);
+
+	/* Create new font bitmap, wider by dwidth pixels */
+	gfx_bitmap_params_init(&params);
+	params.rect = font->rect;
+	params.rect.p1.x += dwidth;
+	if (height > params.rect.p1.y)
+		params.rect.p1.y = height;
+
+	rc = gfx_bitmap_create(font->gc, &params, NULL, &nbitmap);
+	if (rc != EOK)
+		goto error;
+
+	/* Transfer glyphs before @a glyph */
+	g = gfx_font_first_glyph(font);
+	while (g != glyph) {
+		assert(g != NULL);
+
+		rc = gfx_glyph_transfer(g, 0, nbitmap, &params.rect);
+		if (rc != EOK)
+			goto error;
+
+		g = gfx_font_next_glyph(g);
+	}
+
+	/* Skip @a glyph */
+	g = gfx_font_next_glyph(g);
+
+	/* Transfer glyphs after glyph */
+	while (g != NULL) {
+		rc = gfx_glyph_transfer(g, dwidth, nbitmap, &params.rect);
+		if (rc != EOK)
+			goto error;
+
+		/* Update glyph coordinates */
+		g->rect.p0.x += dwidth;
+		g->rect.p1.x += dwidth;
+		g->origin.x += dwidth;
+
+		g = gfx_font_next_glyph(g);
+	}
+
+	/* Update glyph width and height */
+	glyph->rect.p1.x = glyph->rect.p0.x + width;
+	glyph->rect.p1.y = glyph->rect.p0.y + height;
+
+	/* Update font bitmap */
+	gfx_bitmap_destroy(font->bitmap);
+	font->bitmap = nbitmap;
+	font->rect = params.rect;
+
+	return EOK;
+error:
+	if (nbitmap != NULL)
+		gfx_bitmap_destroy(nbitmap);
+	return rc;
+}
+
 /** @}
  */
Index: uspace/lib/gfxfont/src/glyph.c
===================================================================
--- uspace/lib/gfxfont/src/glyph.c	(revision 5592c56bec345742686b5b607eadcd91d62d61de)
+++ uspace/lib/gfxfont/src/glyph.c	(revision d2100e23b019a7ed116b6d3d17c17625196dc4f7)
@@ -36,5 +36,7 @@
 #include <assert.h>
 #include <errno.h>
+#include <gfx/bitmap.h>
 #include <gfx/glyph.h>
+#include <io/pixelmap.h>
 #include <mem.h>
 #include <stdlib.h>
@@ -252,4 +254,50 @@
 }
 
+/** Transfer glyph to new font bitmap.
+ *
+ * @param glyph Glyph
+ * @param offs Offset in new font bitmap
+ * @param dest New font bitmap
+ * @param drect Bounding rectangle for @a dest
+ *
+ * @return EOK on success or an error code
+ */
+errno_t gfx_glyph_transfer(gfx_glyph_t *glyph, gfx_coord_t offs,
+    gfx_bitmap_t *dest, gfx_rect_t *drect)
+{
+	pixelmap_t smap;
+	pixelmap_t dmap;
+	gfx_bitmap_alloc_t salloc;
+	gfx_bitmap_alloc_t dalloc;
+	gfx_coord_t x, y;
+	pixel_t pixel;
+	errno_t rc;
+
+	rc = gfx_bitmap_get_alloc(glyph->font->bitmap, &salloc);
+	if (rc != EOK)
+		return rc;
+
+	rc = gfx_bitmap_get_alloc(dest, &dalloc);
+	if (rc != EOK)
+		return rc;
+
+	smap.width = glyph->font->rect.p1.x;
+	smap.height = glyph->font->rect.p1.y;
+	smap.data = salloc.pixels;
+
+	dmap.width = drect->p1.x;
+	dmap.height = drect->p1.y;
+	dmap.data = dalloc.pixels;
+
+	for (y = drect->p0.y; y < drect->p1.y; y++) {
+		for (x = drect->p0.x; x < drect->p1.x; x++) {
+			pixel = pixelmap_get_pixel(&smap, x, y);
+			pixelmap_put_pixel(&dmap, x + offs, y, pixel);
+		}
+	}
+
+	return EOK;
+}
+
 /** @}
  */
Index: uspace/lib/gfxfont/src/glyph_bmp.c
===================================================================
--- uspace/lib/gfxfont/src/glyph_bmp.c	(revision 5592c56bec345742686b5b607eadcd91d62d61de)
+++ uspace/lib/gfxfont/src/glyph_bmp.c	(revision d2100e23b019a7ed116b6d3d17c17625196dc4f7)
@@ -35,7 +35,12 @@
 
 #include <errno.h>
+#include <gfx/bitmap.h>
 #include <gfx/coord.h>
+#include <gfx/font.h>
 #include <gfx/glyph_bmp.h>
+#include <io/pixelmap.h>
 #include <stdlib.h>
+#include "../private/font.h"
+#include "../private/glyph.h"
 #include "../private/glyph_bmp.h"
 
@@ -50,5 +55,11 @@
 errno_t gfx_glyph_bmp_open(gfx_glyph_t *glyph, gfx_glyph_bmp_t **rbmp)
 {
+	gfx_font_t *font = glyph->font;
 	gfx_glyph_bmp_t *bmp;
+	pixelmap_t pmap;
+	gfx_bitmap_alloc_t alloc;
+	gfx_coord_t x, y;
+	pixel_t pixel;
+	errno_t rc;
 
 	bmp = calloc(1, sizeof(gfx_glyph_bmp_t));
@@ -58,7 +69,36 @@
 	bmp->rect.p0.x = 0;
 	bmp->rect.p0.y = 0;
-	bmp->rect.p1.x = 0;
-	bmp->rect.p1.y = 0;
-	bmp->pixels = NULL;
+	bmp->rect.p1.x = glyph->rect.p1.x - glyph->rect.p0.x;
+	bmp->rect.p1.y = glyph->rect.p1.y - glyph->rect.p0.y;
+
+	bmp->pixels = calloc(bmp->rect.p1.x * bmp->rect.p1.y, sizeof(int));
+	if (bmp->pixels == NULL) {
+		free(bmp);
+		return ENOMEM;
+	}
+
+	rc = gfx_bitmap_get_alloc(font->bitmap, &alloc);
+	if (rc != EOK) {
+		free(bmp->pixels);
+		free(bmp);
+		return rc;
+	}
+
+	assert(font->rect.p0.x == 0);
+	assert(font->rect.p0.y == 0);
+	pmap.width = font->rect.p1.x;
+	pmap.height = font->rect.p1.y;
+	pmap.data = alloc.pixels;
+
+	/* Copy pixels from font bitmap */
+
+	for (y = 0; y < bmp->rect.p1.y; y++) {
+		for (x = 0; x < bmp->rect.p1.x; x++) {
+			pixel = pixelmap_get_pixel(&pmap, glyph->rect.p0.x + x,
+			    glyph->rect.p0.y + y);
+			bmp->pixels[y * bmp->rect.p1.x + x] =
+			    (pixel != 0) ? 1 : 0;
+		}
+	}
 
 	bmp->glyph = glyph;
@@ -74,4 +114,43 @@
 errno_t gfx_glyph_bmp_save(gfx_glyph_bmp_t *bmp)
 {
+	gfx_glyph_t *glyph = bmp->glyph;
+	gfx_font_t *font = glyph->font;
+	gfx_coord_t x, y;
+	pixel_t pixel;
+	pixelmap_t pmap;
+	gfx_bitmap_alloc_t alloc;
+	errno_t rc;
+
+	/*
+	 * Replace glyph with empty space in the font bitmap, the width
+	 * of the empty equal to new glyph bitmap width. The glyph width
+	 * is adjusted.
+	 */
+	rc = gfx_font_splice_at_glyph(font, glyph,
+	    bmp->rect.p1.x - bmp->rect.p0.x, bmp->rect.p1.y - bmp->rect.p0.y);
+	if (rc != EOK)
+		return rc;
+
+	rc = gfx_bitmap_get_alloc(font->bitmap, &alloc);
+	if (rc != EOK)
+		return rc;
+
+	assert(font->rect.p0.x == 0);
+	assert(font->rect.p0.y == 0);
+	pmap.width = font->rect.p1.x;
+	pmap.height = font->rect.p1.y;
+	pmap.data = alloc.pixels;
+
+	/* Copy pixels to font bitmap */
+
+	for (y = 0; y < bmp->rect.p1.y; y++) {
+		for (x = 0; x < bmp->rect.p1.x; x++) {
+			pixel = bmp->pixels[y * bmp->rect.p1.x + x] ?
+			    PIXEL(255, 255, 255, 255) : PIXEL(0, 0, 0, 0);
+			pixelmap_put_pixel(&pmap, glyph->rect.p0.x + x,
+			    glyph->rect.p0.y + y, pixel);
+		}
+	}
+
 	return EOK;
 }
Index: uspace/lib/gfxfont/test/font.c
===================================================================
--- uspace/lib/gfxfont/test/font.c	(revision 5592c56bec345742686b5b607eadcd91d62d61de)
+++ uspace/lib/gfxfont/test/font.c	(revision d2100e23b019a7ed116b6d3d17c17625196dc4f7)
@@ -29,5 +29,7 @@
 #include <gfx/context.h>
 #include <gfx/font.h>
+#include <gfx/glyph.h>
 #include <pcut/pcut.h>
+#include "../private/font.h"
 
 PCUT_INIT;
@@ -37,9 +39,31 @@
 static errno_t testgc_set_color(void *, gfx_color_t *);
 static errno_t testgc_fill_rect(void *, gfx_rect_t *);
+static errno_t testgc_bitmap_create(void *, gfx_bitmap_params_t *,
+    gfx_bitmap_alloc_t *, void **);
+static errno_t testgc_bitmap_destroy(void *);
+static errno_t testgc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
+static errno_t testgc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
 
 static gfx_context_ops_t test_ops = {
 	.set_color = testgc_set_color,
-	.fill_rect = testgc_fill_rect
+	.fill_rect = testgc_fill_rect,
+	.bitmap_create = testgc_bitmap_create,
+	.bitmap_destroy = testgc_bitmap_destroy,
+	.bitmap_render = testgc_bitmap_render,
+	.bitmap_get_alloc = testgc_bitmap_get_alloc
 };
+
+typedef struct {
+	gfx_bitmap_params_t bm_params;
+	void *bm_pixels;
+	gfx_rect_t bm_srect;
+	gfx_coord2_t bm_offs;
+} test_gc_t;
+
+typedef struct {
+	test_gc_t *tgc;
+	gfx_bitmap_alloc_t alloc;
+	bool myalloc;
+} testgc_bitmap_t;
 
 /** Test creating and destroying font */
@@ -49,7 +73,8 @@
 	gfx_font_t *font;
 	gfx_context_t *gc;
-	errno_t rc;
-
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -70,7 +95,8 @@
 	gfx_font_t *font;
 	gfx_context_t *gc;
-	errno_t rc;
-
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -101,7 +127,8 @@
 	gfx_font_t *font;
 	gfx_context_t *gc;
-	errno_t rc;
-
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -136,20 +163,34 @@
 {
 	gfx_font_metrics_t metrics;
+	gfx_glyph_metrics_t gmetrics;
 	gfx_font_t *font;
 	gfx_context_t *gc;
 	gfx_glyph_t *glyph;
-	errno_t rc;
-
-	rc = gfx_context_new(&test_ops, NULL, &gc);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	gfx_font_metrics_init(&metrics);
-
-	rc = gfx_font_create(gc, &metrics, &font);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
+	gfx_glyph_t *gfirst;
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	gfx_font_metrics_init(&metrics);
+
+	rc = gfx_font_create(gc, &metrics, &font);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Should get NULL since there is no glyph in the font */
 	glyph = gfx_font_first_glyph(font);
 	PCUT_ASSERT_NULL(glyph);
 
+	/* Now add one */
+	gfx_glyph_metrics_init(&gmetrics);
+	rc = gfx_glyph_create(font, &gmetrics, &glyph);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* gfx_font_first_glyph() should return the same */
+	gfirst = gfx_font_first_glyph(font);
+	PCUT_ASSERT_EQUALS(glyph, gfirst);
+
+	gfx_glyph_destroy(glyph);
 	gfx_font_destroy(font);
 	rc = gfx_context_delete(gc);
@@ -160,5 +201,46 @@
 PCUT_TEST(next_glyph)
 {
-	/* TODO */
+	gfx_font_metrics_t metrics;
+	gfx_glyph_metrics_t gmetrics;
+	gfx_font_t *font;
+	gfx_context_t *gc;
+	gfx_glyph_t *glyph1;
+	gfx_glyph_t *glyph2;
+	gfx_glyph_t *gfirst;
+	gfx_glyph_t *gsecond;
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	gfx_font_metrics_init(&metrics);
+
+	rc = gfx_font_create(gc, &metrics, &font);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Add first glyph */
+	gfx_glyph_metrics_init(&gmetrics);
+	rc = gfx_glyph_create(font, &gmetrics, &glyph1);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Add second glyph */
+	gfx_glyph_metrics_init(&gmetrics);
+	rc = gfx_glyph_create(font, &gmetrics, &glyph2);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* gfx_font_first_glyph() should return glyph1 */
+	gfirst = gfx_font_first_glyph(font);
+	PCUT_ASSERT_EQUALS(glyph1, gfirst);
+
+	/* gfx_font_next_glyph() should return glyph2 */
+	gsecond = gfx_font_next_glyph(gfirst);
+	PCUT_ASSERT_EQUALS(glyph2, gsecond);
+
+	gfx_glyph_destroy(glyph1);
+	gfx_glyph_destroy(glyph2);
+	gfx_font_destroy(font);
+	rc = gfx_context_delete(gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 }
 
@@ -171,7 +253,8 @@
 	gfx_glyph_t *glyph;
 	size_t bytes;
-	errno_t rc;
-
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -189,4 +272,36 @@
 }
 
+/** Test gfx_font_splice_at_glyph() */
+PCUT_TEST(splice_at_glyph)
+{
+	gfx_font_metrics_t fmetrics;
+	gfx_font_t *font;
+	gfx_glyph_metrics_t gmetrics;
+	gfx_glyph_t *glyph;
+	gfx_context_t *gc;
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	gfx_font_metrics_init(&fmetrics);
+	rc = gfx_font_create(gc, &fmetrics, &font);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	gfx_glyph_metrics_init(&gmetrics);
+	rc = gfx_glyph_create(font, &gmetrics, &glyph);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = gfx_font_splice_at_glyph(font, glyph, 10, 10);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	gfx_glyph_destroy(glyph);
+
+	gfx_font_destroy(font);
+	rc = gfx_context_delete(gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+}
+
 static errno_t testgc_set_color(void *arg, gfx_color_t *color)
 {
@@ -199,3 +314,60 @@
 }
 
+static errno_t testgc_bitmap_create(void *arg, gfx_bitmap_params_t *params,
+    gfx_bitmap_alloc_t *alloc, void **rbm)
+{
+	test_gc_t *tgc = (test_gc_t *) arg;
+	testgc_bitmap_t *tbm;
+
+	tbm = calloc(1, sizeof(testgc_bitmap_t));
+	if (tbm == NULL)
+		return ENOMEM;
+
+	if (alloc == NULL) {
+		tbm->alloc.pitch = (params->rect.p1.x - params->rect.p0.x) *
+		    sizeof(uint32_t);
+		tbm->alloc.off0 = 0;
+		tbm->alloc.pixels = calloc(sizeof(uint32_t),
+		    tbm->alloc.pitch * (params->rect.p1.y - params->rect.p0.y));
+		tbm->myalloc = true;
+		if (tbm->alloc.pixels == NULL) {
+			free(tbm);
+			return ENOMEM;
+		}
+	} else {
+		tbm->alloc = *alloc;
+	}
+
+	tbm->tgc = tgc;
+	tgc->bm_params = *params;
+	tgc->bm_pixels = tbm->alloc.pixels;
+	*rbm = (void *)tbm;
+	return EOK;
+}
+
+static errno_t testgc_bitmap_destroy(void *bm)
+{
+	testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
+	if (tbm->myalloc)
+		free(tbm->alloc.pixels);
+	free(tbm);
+	return EOK;
+}
+
+static errno_t testgc_bitmap_render(void *bm, gfx_rect_t *srect,
+    gfx_coord2_t *offs)
+{
+	testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
+	tbm->tgc->bm_srect = *srect;
+	tbm->tgc->bm_offs = *offs;
+	return EOK;
+}
+
+static errno_t testgc_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
+{
+	testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
+	*alloc = tbm->alloc;
+	return EOK;
+}
+
 PCUT_EXPORT(font);
Index: uspace/lib/gfxfont/test/glyph.c
===================================================================
--- uspace/lib/gfxfont/test/glyph.c	(revision 5592c56bec345742686b5b607eadcd91d62d61de)
+++ uspace/lib/gfxfont/test/glyph.c	(revision d2100e23b019a7ed116b6d3d17c17625196dc4f7)
@@ -27,10 +27,14 @@
  */
 
+#include <gfx/bitmap.h>
 #include <gfx/context.h>
 #include <gfx/font.h>
 #include <gfx/glyph.h>
+#include <gfx/glyph_bmp.h>
+#include <io/pixelmap.h>
 #include <pcut/pcut.h>
 #include <stdbool.h>
 #include <str.h>
+#include "../private/glyph.h"
 
 PCUT_INIT;
@@ -40,9 +44,31 @@
 static errno_t testgc_set_color(void *, gfx_color_t *);
 static errno_t testgc_fill_rect(void *, gfx_rect_t *);
+static errno_t testgc_bitmap_create(void *, gfx_bitmap_params_t *,
+    gfx_bitmap_alloc_t *, void **);
+static errno_t testgc_bitmap_destroy(void *);
+static errno_t testgc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
+static errno_t testgc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
 
 static gfx_context_ops_t test_ops = {
 	.set_color = testgc_set_color,
-	.fill_rect = testgc_fill_rect
+	.fill_rect = testgc_fill_rect,
+	.bitmap_create = testgc_bitmap_create,
+	.bitmap_destroy = testgc_bitmap_destroy,
+	.bitmap_render = testgc_bitmap_render,
+	.bitmap_get_alloc = testgc_bitmap_get_alloc
 };
+
+typedef struct {
+	gfx_bitmap_params_t bm_params;
+	void *bm_pixels;
+	gfx_rect_t bm_srect;
+	gfx_coord2_t bm_offs;
+} test_gc_t;
+
+typedef struct {
+	test_gc_t *tgc;
+	gfx_bitmap_alloc_t alloc;
+	bool myalloc;
+} testgc_bitmap_t;
 
 /** Test creating and destroying glyph */
@@ -54,7 +80,8 @@
 	gfx_glyph_t *glyph;
 	gfx_context_t *gc;
-	errno_t rc;
-
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -83,7 +110,8 @@
 	gfx_glyph_metrics_t rmetrics;
 	gfx_context_t *gc;
-	errno_t rc;
-
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -118,7 +146,8 @@
 	gfx_glyph_metrics_t rmetrics;
 	gfx_context_t *gc;
-	errno_t rc;
-
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -156,7 +185,8 @@
 	gfx_glyph_t *glyph;
 	gfx_context_t *gc;
-	errno_t rc;
-
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -198,7 +228,8 @@
 	gfx_glyph_t *glyph;
 	gfx_context_t *gc;
-	errno_t rc;
-
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -243,9 +274,10 @@
 	gfx_glyph_t *glyph;
 	gfx_context_t *gc;
+	test_gc_t tgc;
 	bool match;
 	size_t msize;
 	errno_t rc;
 
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -296,8 +328,9 @@
 	gfx_glyph_t *glyph;
 	gfx_context_t *gc;
+	test_gc_t tgc;
 	gfx_glyph_pattern_t *pat;
 	errno_t rc;
 
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -340,9 +373,10 @@
 	gfx_glyph_t *glyph;
 	gfx_context_t *gc;
+	test_gc_t tgc;
 	gfx_glyph_pattern_t *pat;
 	const char *pstr;
 	errno_t rc;
 
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -377,4 +411,96 @@
 }
 
+/** Test gfx_glyph_transfer() */
+PCUT_TEST(transfer)
+{
+	gfx_font_metrics_t fmetrics;
+	gfx_font_t *font;
+	gfx_glyph_metrics_t gmetrics;
+	gfx_glyph_t *glyph;
+	gfx_context_t *gc;
+	gfx_bitmap_t *bitmap;
+	gfx_bitmap_params_t params;
+	gfx_bitmap_alloc_t alloc;
+	gfx_glyph_bmp_t *bmp;
+	pixelmap_t pmap;
+	pixel_t pixel;
+	test_gc_t tgc;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	gfx_font_metrics_init(&fmetrics);
+	rc = gfx_font_create(gc, &fmetrics, &font);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	gfx_glyph_metrics_init(&gmetrics);
+	gmetrics.advance = 1;
+
+	rc = gfx_glyph_create(font, &gmetrics, &glyph);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/*
+	 * We need to fill some pixels of the glyph.
+	 * We'll use the glyph bitmap for that.
+	 * That means this test won't pass unless glyph
+	 * bitmap works.
+	 */
+
+	rc = gfx_glyph_bmp_open(glyph, &bmp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(bmp);
+
+	rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 1);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = gfx_glyph_bmp_setpix(bmp, 1, 1, 1);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = gfx_glyph_bmp_save(bmp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	gfx_glyph_bmp_close(bmp);
+
+	/* Now create a new bitmap */
+
+	gfx_bitmap_params_init(&params);
+	params.rect.p0.x = 0;
+	params.rect.p0.y = 0;
+	params.rect.p1.x = 10;
+	params.rect.p1.y = 10;
+	rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = gfx_bitmap_get_alloc(bitmap, &alloc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Transfer the glyph to new bitmap */
+	rc = gfx_glyph_transfer(glyph, 0, bitmap, &params.rect);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Now let's read pixels from the new bitmap */
+	pmap.width = params.rect.p1.x;
+	pmap.height = params.rect.p1.y;
+	pmap.data = alloc.pixels;
+
+	pixel = pixelmap_get_pixel(&pmap, 0, 0);
+	PCUT_ASSERT_INT_EQUALS(PIXEL(255, 255, 255, 255), pixel);
+
+	pixel = pixelmap_get_pixel(&pmap, 1, 1);
+	PCUT_ASSERT_INT_EQUALS(PIXEL(255, 255, 255, 255), pixel);
+
+	pixel = pixelmap_get_pixel(&pmap, 1, 0);
+	PCUT_ASSERT_INT_EQUALS(PIXEL(0, 0, 0, 0), pixel);
+
+	pixel = pixelmap_get_pixel(&pmap, 0, 1);
+	PCUT_ASSERT_INT_EQUALS(PIXEL(0, 0, 0, 0), pixel);
+
+	gfx_glyph_destroy(glyph);
+
+	gfx_font_destroy(font);
+	rc = gfx_context_delete(gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+}
+
 static errno_t testgc_set_color(void *arg, gfx_color_t *color)
 {
@@ -387,3 +513,60 @@
 }
 
+static errno_t testgc_bitmap_create(void *arg, gfx_bitmap_params_t *params,
+    gfx_bitmap_alloc_t *alloc, void **rbm)
+{
+	test_gc_t *tgc = (test_gc_t *) arg;
+	testgc_bitmap_t *tbm;
+
+	tbm = calloc(1, sizeof(testgc_bitmap_t));
+	if (tbm == NULL)
+		return ENOMEM;
+
+	if (alloc == NULL) {
+		tbm->alloc.pitch = (params->rect.p1.x - params->rect.p0.x) *
+		    sizeof(uint32_t);
+		tbm->alloc.off0 = 0;
+		tbm->alloc.pixels = calloc(sizeof(uint32_t),
+		    tbm->alloc.pitch * (params->rect.p1.y - params->rect.p0.y));
+		tbm->myalloc = true;
+		if (tbm->alloc.pixels == NULL) {
+			free(tbm);
+			return ENOMEM;
+		}
+	} else {
+		tbm->alloc = *alloc;
+	}
+
+	tbm->tgc = tgc;
+	tgc->bm_params = *params;
+	tgc->bm_pixels = tbm->alloc.pixels;
+	*rbm = (void *)tbm;
+	return EOK;
+}
+
+static errno_t testgc_bitmap_destroy(void *bm)
+{
+	testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
+	if (tbm->myalloc)
+		free(tbm->alloc.pixels);
+	free(tbm);
+	return EOK;
+}
+
+static errno_t testgc_bitmap_render(void *bm, gfx_rect_t *srect,
+    gfx_coord2_t *offs)
+{
+	testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
+	tbm->tgc->bm_srect = *srect;
+	tbm->tgc->bm_offs = *offs;
+	return EOK;
+}
+
+static errno_t testgc_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
+{
+	testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
+	*alloc = tbm->alloc;
+	return EOK;
+}
+
 PCUT_EXPORT(glyph);
Index: uspace/lib/gfxfont/test/glyph_bmp.c
===================================================================
--- uspace/lib/gfxfont/test/glyph_bmp.c	(revision 5592c56bec345742686b5b607eadcd91d62d61de)
+++ uspace/lib/gfxfont/test/glyph_bmp.c	(revision d2100e23b019a7ed116b6d3d17c17625196dc4f7)
@@ -39,9 +39,31 @@
 static errno_t testgc_set_color(void *, gfx_color_t *);
 static errno_t testgc_fill_rect(void *, gfx_rect_t *);
+static errno_t testgc_bitmap_create(void *, gfx_bitmap_params_t *,
+    gfx_bitmap_alloc_t *, void **);
+static errno_t testgc_bitmap_destroy(void *);
+static errno_t testgc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
+static errno_t testgc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
 
 static gfx_context_ops_t test_ops = {
 	.set_color = testgc_set_color,
-	.fill_rect = testgc_fill_rect
+	.fill_rect = testgc_fill_rect,
+	.bitmap_create = testgc_bitmap_create,
+	.bitmap_destroy = testgc_bitmap_destroy,
+	.bitmap_render = testgc_bitmap_render,
+	.bitmap_get_alloc = testgc_bitmap_get_alloc
 };
+
+typedef struct {
+	gfx_bitmap_params_t bm_params;
+	void *bm_pixels;
+	gfx_rect_t bm_srect;
+	gfx_coord2_t bm_offs;
+} test_gc_t;
+
+typedef struct {
+	test_gc_t *tgc;
+	gfx_bitmap_alloc_t alloc;
+	bool myalloc;
+} testgc_bitmap_t;
 
 /** Test opening and closing glyph bitmap */
@@ -54,7 +76,8 @@
 	gfx_context_t *gc;
 	gfx_glyph_bmp_t *bmp;
+	test_gc_t tgc;
 	errno_t rc;
 
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -86,47 +109,4 @@
 /** Test glyph_bmp_save() */
 PCUT_TEST(save)
-{
-	gfx_font_metrics_t fmetrics;
-	gfx_font_t *font;
-	gfx_glyph_metrics_t gmetrics;
-	gfx_glyph_t *glyph;
-	gfx_context_t *gc;
-	gfx_glyph_bmp_t *bmp;
-	errno_t rc;
-
-	rc = gfx_context_new(&test_ops, NULL, &gc);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	gfx_font_metrics_init(&fmetrics);
-	rc = gfx_font_create(gc, &fmetrics, &font);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	gfx_glyph_metrics_init(&gmetrics);
-	gmetrics.advance = 1;
-
-	rc = gfx_glyph_create(font, &gmetrics, &glyph);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	bmp = NULL;
-
-	rc = gfx_glyph_bmp_open(glyph, &bmp);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-	PCUT_ASSERT_NOT_NULL(bmp);
-
-	/* TODO: Need a test to verify that save actually worked */
-	rc = gfx_glyph_bmp_save(bmp);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	gfx_glyph_bmp_close(bmp);
-
-	gfx_glyph_destroy(glyph);
-
-	gfx_font_destroy(font);
-	rc = gfx_context_delete(gc);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-}
-
-/** Test glyph_bmp_getpix() */
-PCUT_TEST(getpix)
 {
 	gfx_font_metrics_t fmetrics;
@@ -137,7 +117,8 @@
 	gfx_glyph_bmp_t *bmp;
 	int pix;
+	test_gc_t tgc;
 	errno_t rc;
 
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -154,4 +135,24 @@
 	bmp = NULL;
 
+	/* Open bitmap and set some pixels */
+
+	rc = gfx_glyph_bmp_open(glyph, &bmp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(bmp);
+
+	rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 1);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = gfx_glyph_bmp_setpix(bmp, 1, 1, 1);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = gfx_glyph_bmp_save(bmp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	gfx_glyph_bmp_close(bmp);
+	bmp = NULL;
+
+	/* Re-open the saved bimap and verify pixel values were preserved */
+
 	rc = gfx_glyph_bmp_open(glyph, &bmp);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
@@ -159,8 +160,16 @@
 
 	pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
+	PCUT_ASSERT_INT_EQUALS(1, pix);
+
+	pix = gfx_glyph_bmp_getpix(bmp, 1, 1);
+	PCUT_ASSERT_INT_EQUALS(1, pix);
+
+	pix = gfx_glyph_bmp_getpix(bmp, 1, 0);
 	PCUT_ASSERT_INT_EQUALS(0, pix);
 
-	gfx_glyph_bmp_close(bmp);
-
+	pix = gfx_glyph_bmp_getpix(bmp, 0, 1);
+	PCUT_ASSERT_INT_EQUALS(0, pix);
+
+	gfx_glyph_bmp_close(bmp);
 	gfx_glyph_destroy(glyph);
 
@@ -170,6 +179,6 @@
 }
 
-/** Test glyph_bmp_setpix() can flip pixel value both ways */
-PCUT_TEST(setpix_flip)
+/** Test glyph_bmp_getpix() */
+PCUT_TEST(getpix)
 {
 	gfx_font_metrics_t fmetrics;
@@ -179,8 +188,53 @@
 	gfx_context_t *gc;
 	gfx_glyph_bmp_t *bmp;
+	test_gc_t tgc;
 	int pix;
 	errno_t rc;
 
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	gfx_font_metrics_init(&fmetrics);
+	rc = gfx_font_create(gc, &fmetrics, &font);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	gfx_glyph_metrics_init(&gmetrics);
+	gmetrics.advance = 1;
+
+	rc = gfx_glyph_create(font, &gmetrics, &glyph);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	bmp = NULL;
+
+	rc = gfx_glyph_bmp_open(glyph, &bmp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(bmp);
+
+	pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
+	PCUT_ASSERT_INT_EQUALS(0, pix);
+
+	gfx_glyph_bmp_close(bmp);
+
+	gfx_glyph_destroy(glyph);
+
+	gfx_font_destroy(font);
+	rc = gfx_context_delete(gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+}
+
+/** Test glyph_bmp_setpix() can flip pixel value both ways */
+PCUT_TEST(setpix_flip)
+{
+	gfx_font_metrics_t fmetrics;
+	gfx_font_t *font;
+	gfx_glyph_metrics_t gmetrics;
+	gfx_glyph_t *glyph;
+	gfx_context_t *gc;
+	gfx_glyph_bmp_t *bmp;
+	test_gc_t tgc;
+	int pix;
+	errno_t rc;
+
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -235,8 +289,9 @@
 	gfx_glyph_bmp_t *bmp;
 	gfx_coord_t x, y;
+	test_gc_t tgc;
 	int pix;
 	errno_t rc;
 
-	rc = gfx_context_new(&test_ops, NULL, &gc);
+	rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -303,3 +358,60 @@
 }
 
+static errno_t testgc_bitmap_create(void *arg, gfx_bitmap_params_t *params,
+    gfx_bitmap_alloc_t *alloc, void **rbm)
+{
+	test_gc_t *tgc = (test_gc_t *) arg;
+	testgc_bitmap_t *tbm;
+
+	tbm = calloc(1, sizeof(testgc_bitmap_t));
+	if (tbm == NULL)
+		return ENOMEM;
+
+	if (alloc == NULL) {
+		tbm->alloc.pitch = (params->rect.p1.x - params->rect.p0.x) *
+		    sizeof(uint32_t);
+		tbm->alloc.off0 = 0;
+		tbm->alloc.pixels = calloc(sizeof(uint32_t),
+		    tbm->alloc.pitch * (params->rect.p1.y - params->rect.p0.y));
+		tbm->myalloc = true;
+		if (tbm->alloc.pixels == NULL) {
+			free(tbm);
+			return ENOMEM;
+		}
+	} else {
+		tbm->alloc = *alloc;
+	}
+
+	tbm->tgc = tgc;
+	tgc->bm_params = *params;
+	tgc->bm_pixels = tbm->alloc.pixels;
+	*rbm = (void *)tbm;
+	return EOK;
+}
+
+static errno_t testgc_bitmap_destroy(void *bm)
+{
+	testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
+	if (tbm->myalloc)
+		free(tbm->alloc.pixels);
+	free(tbm);
+	return EOK;
+}
+
+static errno_t testgc_bitmap_render(void *bm, gfx_rect_t *srect,
+    gfx_coord2_t *offs)
+{
+	testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
+	tbm->tgc->bm_srect = *srect;
+	tbm->tgc->bm_offs = *offs;
+	return EOK;
+}
+
+static errno_t testgc_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
+{
+	testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
+	*alloc = tbm->alloc;
+	return EOK;
+}
+
 PCUT_EXPORT(glyph_bmp);
