diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index 4e0cc42..b2a5870 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -428,6 +428,19 @@ struct gui_img* find_image(char label, struct wps_data *data)
     }
     return NULL;
 }
+
+struct skin_font* find_font(int id, struct wps_data *data)
+{
+    struct skin_token_list *list = data->fonts;
+    while (list)
+    {
+        struct skin_font *f = (struct skin_font*)list->token->value.data;
+        if (f->id == id)
+            return f;
+        list = list->next;
+    }
+    return NULL;
+}
 #endif

 /* traverse the viewport linked list for a viewport */
@@ -695,14 +708,14 @@ static int parse_image_load(const char *wps_bufptr,
 /* this array acts as a simple mapping between the id the user uses for a font
  * and the id the font actually gets from the font loader.
  * font id 2 is always the first skin font (regardless of how many screens */
-static int font_ids[MAXUSERFONTS];
 static int parse_font_load(const char *wps_bufptr,
         struct wps_token *token, struct wps_data *wps_data)
 {
     (void)wps_data; (void)token;
     const char *ptr = wps_bufptr;
     int id;
-    char *filename, buf[MAX_PATH];
+    char *filename;
+    struct skin_font *font;

     if (*ptr != '|')
         return WPS_ERROR_INVALID_PARAM;
@@ -718,13 +731,25 @@ static int parse_font_load(const char *wps_bufptr,

     if (id <= FONT_UI || id >= MAXFONTS-1)
         return WPS_ERROR_INVALID_PARAM;
-    id -= FONT_UI;
-    
-    memcpy(buf, filename, ptr-filename);
-    buf[ptr-filename] = '\0';
-    font_ids[id] = skin_font_load(buf);
-    
-    return font_ids[id] >= 0 ? skip_end_of_line(wps_bufptr) : WPS_ERROR_INVALID_PARAM;
+
+    font = skin_buffer_alloc(sizeof(struct skin_font));
+    int len = ptr-filename+1;
+    char* name = skin_buffer_alloc(len);
+    if (!font || !name)
+        return WPS_ERROR_INVALID_PARAM;
+
+    strlcpy(name, filename, len);
+    font->id = id;
+    font->font_id = -1;
+    font->name = name;
+
+    struct skin_token_list *item = new_skin_token_list_item(NULL, font);
+
+    if (!item)
+        return WPS_ERROR_INVALID_PARAM;
+    add_to_ll_chain(&wps_data->fonts, item);
+
+    return skip_end_of_line(wps_bufptr);
 }


@@ -930,9 +955,6 @@ static int parse_viewport(const char *wps_bufptr,
     else
         vp->flags &= ~VP_FLAG_ALIGN_RIGHT; /* ignore right-to-left languages */

-    if (vp->font > FONT_UI)
-        vp->font = font_ids[vp->font - FONT_UI];
-
     struct skin_token_list *list = new_skin_token_list_item(NULL, skin_vp);
     if (!list)
         return WPS_ERROR_INVALID_PARAM;
@@ -2057,6 +2079,31 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir)
     return true;
 }

+static bool skin_load_fonts(struct wps_data *data)
+{
+    struct skin_token_list *vp_list;
+    for(vp_list = data->viewports; vp_list; vp_list = vp_list->next)
+    {
+        /* first, find the viewports that have a non-sys/ui-font font */
+        struct skin_viewport *vp =
+                (struct skin_viewport*)vp_list->token->value.data;
+        if (vp->vp.font <= FONT_UI)
+            continue;
+        /* now find the corresponding skin_font */
+        struct skin_font *font = find_font(vp->vp.font, data);
+        if (!font)
+            return false;
+        /* load the font - will handle loading the same font again if
+         * multiple viewports use the same */
+        font->font_id = skin_font_load(font->name);
+        if (font->font_id < 0)
+            return false;
+        /* finally, assign the font_id to the viewport */
+        vp->vp.font = font->font_id;
+    }
+    return true;
+}
+
 #endif /* HAVE_LCD_BITMAP */

 /* to setup up the wps-data from a format-buffer (isfile = false)
@@ -2173,6 +2220,12 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
             wps_data->wps_loaded = false;
             return false;
         }
+        if (!skin_load_fonts(wps_data))
+        {
+            skin_data_reset(wps_data);
+            wps_data->wps_loaded = false;
+            return false;
+        }
 #endif
 #if defined(HAVE_ALBUMART) && !defined(__PCTOOL__)
         status = audio_status();
diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h
index 04a295a..5fd0678 100644
--- a/apps/gui/skin_engine/wps_internals.h
+++ b/apps/gui/skin_engine/wps_internals.h
@@ -262,6 +262,12 @@ struct skin_albumart {
 };
 #endif

+struct skin_font {
+    int id; /* the id used in the %V tags */
+    int font_id; /* the id returned by font_load */
+    char *name;  /* filename without path and extension */
+};
+
 /* wps_data
    this struct holds all necessary data which describes the
    viewable content of a wps */
@@ -270,6 +276,7 @@ struct wps_data
 #ifdef HAVE_LCD_BITMAP
     struct skin_token_list *images;
     struct skin_token_list *progressbars;
+    struct skin_token_list *fonts;
 #endif
 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
     char *backdrop;