New feature for the %xd() (display a preloaded image) skin tag.
It can now automatically load the correct subimage from a strip (assuming the strip is in the correct order)  by giving a tag for the 2nd param.
example: %xd(F, %mp) which is equivilant to %?mp<%xd(Fa)|%xd(Fb)|%xd(Fc)|%xd(Fd)|%xd(Fe)>
You can also set the subimage offset.. i.e %xd(E, %mm, -1) which means "show nothing for the first value of %mm and use the bitmap strip for the remaining values"

if a tag+offset is <0 or greater than the number of subimages in a strip he image is cleared (I'm open to changing this if someone has a better idea)

cabbiev2.176x220x16.wps is an example of how to use this

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27717 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index a3cb689..c5acd1f 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -232,27 +232,39 @@
     char sublabel = text[1];
     int subimage;
     struct gui_img *img;
+    struct image_display *id = skin_buffer_alloc(sizeof(struct image_display));
 
     /* sanity check */
     img = find_image(label, wps_data);
-    if (!img)
+    if (!img || !id)
     {
         token->value.i = label; /* so debug works */
         return WPS_ERROR_INVALID_PARAM;
     }
-
-    if ((subimage = get_image_id(sublabel)) != -1)
+    id->label = label;
+    id->offset = 0;
+    
+    if (element->params_count > 1)
     {
-        if (subimage >= img->num_subimages)
-            return WPS_ERROR_INVALID_PARAM;
-
-        /* Store sub-image number to display in high bits */
-        token->value.i = label | (subimage << 8);
-        return 4; /* We have consumed 2 bytes */
-    } else {
-        token->value.i = label;
-        return 3; /* We have consumed 1 byte */
+        id->token = element->params[1].data.code->data;
+        if (element->params_count > 2)
+            id->offset = element->params[2].data.number;
     }
+    else
+    {
+        id->token = NULL;
+        if ((subimage = get_image_id(sublabel)) != -1)
+        {
+            if (subimage >= img->num_subimages)
+                return WPS_ERROR_INVALID_PARAM;
+            id->subimage = subimage;
+            token->value.i = label | (subimage << 8);
+        } else {
+            id->subimage = 0;
+        }
+    }
+    token->value.data = id;
+    return 0;
 }
 
 static int parse_image_load(struct skin_element *element,
diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c
index 8957463..e254c62 100644
--- a/apps/gui/skin_engine/skin_render.c
+++ b/apps/gui/skin_engine/skin_render.c
@@ -144,11 +144,36 @@
 #ifdef HAVE_LCD_BITMAP
         case SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY:
         {
-            char n = token->value.i & 0xFF;
-            int subimage = token->value.i >> 8;
+            struct image_display *id = token->value.data;
+            char n = id->label;
             struct gui_img *img = find_image(n, data);
             if (img && img->loaded)
-                img->display = subimage;
+            {
+                if (id->token == NULL)
+                {
+                    img->display = id->subimage;
+                }
+                else
+                {
+                    char buf[16];
+                    const char *out;
+                    int a = TOKEN_VALUE_ONLY;
+                    out = get_token_value(gwps, id->token, buf, sizeof(buf), &a);
+                    /* NOTE: get_token_value() returns values starting at 1! */
+                    if (a == -1)
+                        a = (out && *out) ? 1 : 2;
+                    a--;
+                    a += id->offset;
+                    /* If the token returned a value which is higher than
+                     * the amount of subimages clear the image. */
+                    if (a<0 || a >= img->num_subimages)
+                    {
+                        clear_image_pos(gwps, img);
+                    }
+                    else
+                        img->display = a;
+                }
+            }
             break;
         }
 #ifdef HAVE_ALBUMART
@@ -230,7 +255,8 @@
             /* clear all pictures in the conditional and nested ones */
             if (token->type == SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY)
             {
-                struct gui_img *img = find_image(token->value.i&0xFF, data);
+                struct image_display *id = token->value.data;
+                struct gui_img *img = find_image(id->label, data);
                 clear_image_pos(gwps, img);
             }
             else if (token->type == SKIN_TOKEN_PEAKMETER)
diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h
index 709dbc6..e42fc5a 100644
--- a/apps/gui/skin_engine/wps_internals.h
+++ b/apps/gui/skin_engine/wps_internals.h
@@ -49,6 +49,9 @@
 #define WPS_ALIGN_CENTER 64
 #define WPS_ALIGN_LEFT 128
 
+
+#define TOKEN_VALUE_ONLY 0xDEADD0D0
+
 #ifdef HAVE_ALBUMART
 
 /* albumart definitions */
@@ -80,6 +83,12 @@
     int display;
 };
 
+struct image_display {
+    char label;
+    int subimage;
+    struct wps_token *token; /* the token to get the subimage number from */
+    int offset; /* offset into the bitmap strip to start */
+};
 
 struct progressbar {
     enum skin_token_type type;
diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c
index 26c049b..dccb9f8 100644
--- a/lib/skin_parser/tag_table.c
+++ b/lib/skin_parser/tag_table.c
@@ -167,7 +167,7 @@
     { SKIN_TOKEN_DRAW_INBUILTBAR,       "wi", "", SKIN_REFRESH_STATIC|NOBREAK },
     
     { SKIN_TOKEN_IMAGE_PRELOAD,         "xl", "SFII|I", 0|NOBREAK },
-    { SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", "S", 0 },
+    { SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", "S|TI", 0 },
     { SKIN_TOKEN_IMAGE_DISPLAY,         "x", "SFII", 0|NOBREAK },
     
     { SKIN_TOKEN_LOAD_FONT,             "Fl" , "IF", 0|NOBREAK },
diff --git a/manual/appendix/wps_tags.tex b/manual/appendix/wps_tags.tex
index 070d191..2992b18 100644
--- a/manual/appendix/wps_tags.tex
+++ b/manual/appendix/wps_tags.tex
@@ -320,10 +320,15 @@
           \config{y}: y coordinate\newline
           \config{nimages}: (optional) number of sub-images (tiled vertically, of the same height)
           contained in the bitmap. Default is 1.\\
-    \config{\%xd(n[i])} & Display a preloaded image.
+    \config{\%xd(n[i] [,tag] [,offset])} & Display a preloaded image.
           \config{n}: image ID (a-z and A-Z) as it was specified in \config{\%x} or \config{\%xl}\newline
-          \config{i}: (optional) number of the sub-image to display (a-z for 1-26 and A-Z for 27-52).
-          By default the first (i.e. top most) sub-image will be used.\\
+          \config{i}: (optional) number of the sub-image to display (a-z for 1-26 and A-Z for 27-52). 
+          (ignored when \config{tag} is used)
+          By default the first (i.e. top most) sub-image will be used.\newline
+          \config{tag}: (optional) Another tag to calculate the subimage from e.g \config{\%xd(A, \%mh)} would
+          use the first subimage when \config{\%mh} is on and the second when it is off\newline
+          \config{offset}}: (optional) Add this number to the value from the \config{tag} when 
+          chosing the subimage (may be negative)\\
   \end{tagmap}
 
 Examples:
diff --git a/wps/cabbiev2.176x220x16.wps b/wps/cabbiev2.176x220x16.wps
index c0c7cfc..7b20adf 100644
--- a/wps/cabbiev2.176x220x16.wps
+++ b/wps/cabbiev2.176x220x16.wps
@@ -27,10 +27,10 @@
 %?C<%s%ac%?id<%id|%?d(1)<%d(1)|%(root%)>>|>
 
 %al    %pc%ac%?Sr<%pe %Sx(of) %pp|%pp %Sx(of) %pe>%ar%pr   
-%?mh<%xd(Aa)|%xd(Ab)>
+%xd(A, %mh)
 %?bp<%?bc<%xd(Ba)|%xd(Bb)>|%?bl<|%xd(Bc)|%xd(Bd)|%xd(Be)|%xd(Bf)|%xd(Bg)|%xd(Bh)|%xd(Bi)|%xd(Bj)>>
 %?pv<%xd(Ca)|%xd(Cb)|%xd(Cc)|%xd(Cd)|%xd(Ce)|%xd(Cf)|%xd(Cg)|%xd(Ch)|%xd(Ci)|%xd(Cj)>
 %?ps<%xd(D)>
-%?mm<|%xd(Ea)|%xd(Eb)|%xd(Ec)|%xd(Ed)>
-%?mp<%xd(Fa)|%xd(Fb)|%xd(Fc)|%xd(Fd)|%xd(Fe)>
+%xd(E, %mm, -1)
+%xd(F, %mp)
 %?C<%Cd>