1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
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;