Greg Haerr's font patch 3:
Rotates the font bitmaps only once at font_init() time, with some source
cleanup to rockbox standards.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2284 a1c6a512-1295-4272-9138-f99709370657
diff --git a/firmware/font.c b/firmware/font.c
index 5bde2ff..5237f7d 100644
--- a/firmware/font.c
+++ b/firmware/font.c
@@ -49,6 +49,10 @@
     { NULL,       NULL	        }, /* no FONT_MP3*/
 };
 
+static void rotate_font_bits(PMWCFONT pf);
+static void rotleft(unsigned char *dst, MWIMAGEBITS *src, unsigned int width,
+                unsigned int height);
+
 void
 font_init(void)
 {
@@ -62,6 +66,10 @@
                 DEBUGF("Font load failed: %s\n", cfp->diskname);
 #endif
         }
+
+        /* one-time rotate font bits to rockbox format*/
+        if (cfp->pf && cfp->pf->height)
+            rotate_font_bits(cfp->pf);
     }
 }
 
@@ -107,7 +115,6 @@
     int width = 0;
 
     while((ch = *str++)) {
-
 	/* check input range*/
 	if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
 		ch = pf->defaultchar;
@@ -123,6 +130,70 @@
 }
 
 /*
+ * Put a string at specified bit position
+ */
+//FIXME rename font_putsxy?
+void
+lcd_putsxy(int x, int y, unsigned char *str, int font)
+{
+    int ch;
+    PMWCFONT pf = getfont(font);
+
+    while (((ch = *str++) != '\0')) {
+        MWIMAGEBITS *bits;
+        int width;
+
+        /* check input range*/
+        if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
+            ch = pf->defaultchar;
+        ch -= pf->firstchar;
+
+        /* get proportional width and glyph bits*/
+        width = pf->width? pf->width[ch]: pf->maxwidth;
+        if(x + width > LCD_WIDTH)
+            break;
+        bits = pf->bits + (pf->offset? pf->offset[ch]: (pf->height * ch));
+
+        lcd_bitmap((unsigned char *)bits, x, y, width, pf->height, true);
+        x += width;
+    }
+}
+
+/* convert font bitmap data inplace to rockbox format*/
+static void
+rotate_font_bits(PMWCFONT pf)
+{
+    int i;
+    int defaultchar = pf->defaultchar - pf->firstchar;
+    int did_defaultchar = 0;
+    unsigned char buf[256];
+
+    for (i=0; i<pf->size; ++i) {
+        MWIMAGEBITS *bits = pf->bits +
+            (pf->offset? pf->offset[i]: (pf->height * i));
+        int width = pf->width? pf->width[i]: pf->maxwidth;
+        int src_bytes = MWIMAGE_BYTES(width) * pf->height;
+
+        /*
+         * Due to the way the offset map works,
+         * non-mapped characters are mapped to the default
+         * character, and shouldn't be rotated twice.
+         */
+        if (i == defaultchar) {
+            if (did_defaultchar)
+                continue;
+            did_defaultchar = 1;
+        }
+
+        /* rotate left for lcd_bitmap function input*/
+        rotleft(buf, bits, width, pf->height);
+
+        /* copy back into original location*/
+        memcpy(bits, buf, src_bytes);
+    }
+}
+
+/*
  * Take an MWIMAGEBITS bitmap and convert to Rockbox format.
  * Used for converting font glyphs for the time being.
  * Can use for standard X11 and Win32 images as well.
@@ -147,7 +218,7 @@
     src_words = MWIMAGE_WORDS(width) * height;
 
     /* clear background*/
-    memset(dst, 0, dst_linelen*height);
+    memset(dst, 0, dst_linelen*width);
 
     for (i=0; i < src_words; i++) {
         MWIMAGEBITS srcmap;	/* current src input bit*/
@@ -178,45 +249,9 @@
 		/* input column j becomes output row*/
                 dst[j*dst_linelen + dst_col] |= dstmap;
             }
-	    //printf((bit & src[i])? "*": ".");
+            /*debugf((bit & src[i])? "*": ".");*/
         }
-        //printf("\n");
-    }
-}
-
-/*
- * Put a string at specified bit position
- */
-//FIXME rename font_putsxy?
-void
-lcd_putsxy(int x, int y, unsigned char *str, int font)
-{
-    int ch;
-    unsigned char *src;
-    PMWCFONT pf = getfont(font);
-
-    while (((ch = *str++) != '\0')) {
-	MWIMAGEBITS *bits;
-	int width;
-	unsigned char outbuf[256];
-
-	/* check input range*/
-	if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
-		ch = pf->defaultchar;
-	ch -= pf->firstchar;
-
-	/* get proportional width and glyph bits*/
-	width = pf->width? pf->width[ch]: pf->maxwidth;
-        if(x + width > LCD_WIDTH)
-            break;
-	bits = pf->bits + (pf->offset? pf->offset[ch]: (pf->height * ch));
-
-	/* rotate left for lcd_bitmap function input*/
-	rotleft(outbuf, bits, width, pf->height);
-	src = outbuf;
-
-        lcd_bitmap (src, x, y, width, pf->height, true);
-        x += width;
+        /*debugf("\n");*/
     }
 }
 #endif /* HAVE_LCD_BITMAP */
@@ -224,5 +259,6 @@
 /* -----------------------------------------------------------------
  * local variables:
  * eval: (load-file "rockbox-mode.el")
+ * vim: et sw=4 ts=4 sts=4 tw=78
  * end:
  */
diff --git a/firmware/font.h b/firmware/font.h
index 13d60e5..8535ab2 100644
--- a/firmware/font.h
+++ b/firmware/font.h
@@ -70,7 +70,7 @@
 
 /* MWIMAGEBITS helper macros*/
 #define MWIMAGE_WORDS(x)	(((x)+15)/16)	/* image size in words*/
-#define MWIMAGE_BYTES(x)	(((x)+7)/8)	/* image size in bytes*/
+#define MWIMAGE_BYTES(x)	(MWIMAGE_WORDS(x)*sizeof(MWIMAGEBITS))
 #define	MWIMAGE_BITSPERIMAGE	(sizeof(MWIMAGEBITS) * 8)
 #define	MWIMAGE_BITVALUE(n)	((MWIMAGEBITS) (((MWIMAGEBITS) 1) << (n)))
 #define	MWIMAGE_FIRSTBIT	(MWIMAGE_BITVALUE(MWIMAGE_BITSPERIMAGE - 1))