Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 7:6cf21b018420, committed 2010-11-01
- Comitter:
- richardparker
- Date:
- Mon Nov 01 13:07:40 2010 +0000
- Parent:
- 6:4fe6f365cbeb
- Commit message:
- Embedded Artists LCD panel:- Version 0.7
Changed in this revision
--- a/extras/EASettings.cpp	Thu May 06 23:32:14 2010 +0000
+++ b/extras/EASettings.cpp	Mon Nov 01 13:07:40 2010 +0000
@@ -237,6 +237,9 @@
       
     font.load("/local/large.fnt");   
     _lcd.setFont(font);
+    
+    // DEBUG
+    printf("Font set\r\n");
 
     brush.setColor(black);
     _lcd.setBrush(brush);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fonts/EAFont.cpp	Mon Nov 01 13:07:40 2010 +0000
@@ -0,0 +1,124 @@
+// Copyright 2010 Richard Parker
+
+#include "mbed.h"
+#include "EAFont.h"
+
+#include "EAFontCache.h"
+#include "EAFontCacheEntry.h"
+#include "../screen/EALCD.h"
+#include "../images/EAImage.h"
+
+EAFont::EAFont()
+:   _entry(NULL)
+{
+}
+
+EAFont::~EAFont()
+{
+    // Return reference to characters.
+    if (_entry != NULL)
+    {
+        EAFontCache::instance().returnCharacters(_entry);
+        _entry = NULL;
+    }
+}
+
+EAFont::EAFont(const EAFont& font)
+{   
+    // Do copy like this to ensure that the references in the cache are kept up-to-date.
+    if (font._entry != NULL)
+    {
+        _entry = EAFontCache::instance().getCharacters(font._entry->path());
+    } else {
+        _entry = NULL;
+    }
+}
+
+EAFont& EAFont::operator=(const EAFont& font)
+{
+    if (&font == this)
+    {
+        return *this;
+    }
+
+    // Return the current entry.
+    if (_entry != NULL)
+    {
+        EAFontCache::instance().returnCharacters(_entry);
+        _entry = NULL;
+    }
+
+    // Do copy like this to ensure that the references in the cache are kept up-to-date.
+    if (font._entry != NULL)
+    {
+        _entry = EAFontCache::instance().getCharacters(font._entry->path());
+    } else {
+        _entry = NULL;
+    }
+    
+    return *this;
+}
+
+
+bool EAFont::load(const std::string& path)
+{
+    if (path.empty() == true)
+    {
+        // Invalid path passed in.
+        return false;
+    }
+    
+    // Return entry if needed.
+    if (_entry != NULL)
+    {
+        EAFontCache::instance().returnCharacters(_entry);
+        _entry = NULL;
+    }
+       
+    // Load font descriptor into look up table.  
+    _entry = EAFontCache::instance().getCharacters(path);
+
+    if (_entry == NULL)
+    {
+        return false;
+    }
+      
+    return true;    
+}
+
+bool EAFont::isValid() const 
+{ 
+    return (_entry != NULL);
+}
+
+bool EAFont::_getCharacter(char c, EACharacter& detail)
+{
+    if (_entry == NULL)
+    {
+        return false;
+    }
+
+    for (int i = 0; i < _entry->noChars(); i++)
+    {
+        if (_entry->chars()[i].id == c)
+        {
+            detail = _entry->chars()[i];
+            return true;
+        }
+    }
+    
+    return false;
+}
+
+bool EAFont::_data(EAImage& image) 
+{ 
+    if (_entry == NULL)
+    {
+        return false;
+    }
+    
+    image = _entry->data();
+    
+    return true;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fonts/EAFont.h	Mon Nov 01 13:07:40 2010 +0000
@@ -0,0 +1,52 @@
+// Copyright 2010 Richard Parker
+
+#ifndef MBED_EAFONT_H
+#define MBED_EAFONT_H
+
+#include "mbed.h"
+
+#include <string>
+
+class EALCD;
+class EAFontCacheEntry;
+class EAImage;
+
+/**
+ * Class to handle the font for the EA LCD.
+ * @author Richard Parker
+ */
+class EAFont
+{
+public:
+    friend EALCD;
+    
+    struct EACharacter
+    {
+        unsigned char id;
+        unsigned char x;
+        unsigned char y;
+        unsigned char width;
+        unsigned char height;
+        unsigned char xOffset;
+        unsigned char yOffset;
+        unsigned char xAdvance;
+    };
+
+    EAFont();   
+    ~EAFont();
+       
+    EAFont(const EAFont& font);
+    EAFont& operator=(const EAFont& font);
+       
+    bool isValid() const;
+    bool load(const std::string& path);
+    
+//private:
+    EAFontCacheEntry* _entry;
+
+    bool _getCharacter(char c, EACharacter& detail);
+    bool _data(EAImage& image);
+    
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fonts/EAFontCache.cpp	Mon Nov 01 13:07:40 2010 +0000
@@ -0,0 +1,148 @@
+// Copyright 2010 Richard Parker
+
+#include "mbed.h"
+#include "EAFontCache.h"
+
+EAFontCache::EAFontCache()
+{
+}
+
+EAFontCache::~EAFontCache()
+{
+    // Free any memory associated with the list.
+    _clearCacheEntries();
+}
+
+EAFontCache& EAFontCache::instance()
+{
+    // Only instantiated when getInstance() is called.
+    static EAFontCache instance; 
+    return instance;
+}
+
+void EAFontCache::_clearCacheEntries()
+{
+    std::vector<EAFontCacheEntry*>::iterator it;
+    it = _entries.begin();
+
+    while (it != _entries.end())
+    {
+        delete *it;
+        
+        _entries.erase(it);
+            
+        it = _entries.begin();
+    }    
+}
+
+void EAFontCache::_deleteCacheEntry(EAFontCacheEntry* entry)
+{
+    if (entry == NULL)
+    {
+        return;
+    }
+
+    std::vector<EAFontCacheEntry*>::iterator it;
+    it = _entries.begin();
+
+    while (it != _entries.end())
+    {
+        if (*it == entry)
+        {
+            delete *it;
+        
+            _entries.erase(it);
+            
+            // Can only have one.
+            break;
+        }
+    
+        ++it;
+    }    
+}
+
+EAFontCacheEntry* EAFontCache::_createCacheEntry()
+{
+    EAFontCacheEntry* newEntry = new EAFontCacheEntry();
+    
+    _entries.push_back(newEntry);
+    
+    return newEntry;
+}
+
+EAFontCacheEntry* EAFontCache::getCharacters(const std::string& path)
+{
+    if (path.empty() == true)
+    {
+        return NULL;
+    }
+
+    std::vector<EAFontCacheEntry*>::iterator it;
+    it = _entries.begin();
+
+    // Try to find if we do then increment the references.
+    while (it != _entries.end())
+    {
+        if ((*it)->path() == path)
+        {
+            // Match so return the value.
+            (*it)->incReferences();
+            break;
+        }
+    
+        ++it;
+    }     
+            
+    if (it == _entries.end())
+    {
+        // Not found so want to make new entry.
+        EAFontCacheEntry* current = _createCacheEntry();
+
+        if (current != NULL)
+        {
+            if (current->load(path) == false)
+            {
+                _deleteCacheEntry(current);
+                return NULL;
+            } else {
+                // Increment the reference count.
+                current->incReferences();
+                return current;
+            }
+        } else {
+            return NULL;
+        }
+    } else {          
+        return *it;
+    }
+}
+
+void EAFontCache::returnCharacters(EAFontCacheEntry* entry)
+{
+    if (entry == NULL)
+    {
+        return;
+    }
+
+    std::vector<EAFontCacheEntry*>::iterator it;
+    it = _entries.begin();
+
+    // Try to find if we do then increment the references.
+    while (it != _entries.end())
+    {
+        if ((*it) == entry)
+        {
+            // Match so decrement the references.
+            entry->decReferences();
+                       
+            if (entry->references() <= 0)
+            {
+                _deleteCacheEntry(entry);
+            }
+            
+            break;
+        }
+        
+        ++it;
+    }    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fonts/EAFontCache.h	Mon Nov 01 13:07:40 2010 +0000
@@ -0,0 +1,39 @@
+// Copyright 2010 Richard Parker
+
+#ifndef MBED_EAFONTCACHE_H
+#define MBED_EAFONTCACHE_H
+
+#include "mbed.h"
+#include <string>
+#include <vector>
+
+#include "EAFontCacheEntry.h"
+
+/**
+ * Class to handle the font cache for the EA LCD.
+ * @author Richard Parker
+ */
+class EAFontCache
+{
+public:    
+    static EAFontCache& instance();
+    
+    EAFontCacheEntry* getCharacters(const std::string& path);
+    void returnCharacters(EAFontCacheEntry* entry);
+    
+private:
+    std::vector<EAFontCacheEntry*> _entries;
+
+    EAFontCache();   
+    ~EAFontCache();
+
+    EAFontCache(const EAFontCache&);             // intentionally undefined
+    EAFontCache& operator=(const EAFontCache&);  // intentionally undefined
+
+    void _clearCacheEntries();
+    void _deleteCacheEntry(EAFontCacheEntry* entry);
+    EAFontCacheEntry* _createCacheEntry();
+    
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fonts/EAFontCacheEntry.cpp	Mon Nov 01 13:07:40 2010 +0000
@@ -0,0 +1,126 @@
+// Copyright 2010 Richard Parker
+
+#include "mbed.h"
+#include "EAFontCacheEntry.h"
+
+EAFontCacheEntry::EAFontCacheEntry()
+:    _refs(0)
+{
+}
+
+EAFontCacheEntry::~EAFontCacheEntry()
+{
+    // Remember to free up allocated memory.
+    unload();
+}
+
+void EAFontCacheEntry::unload()
+{   
+    _path.clear();
+
+    _chars.clear();
+    
+    _img.unload();
+}
+
+bool EAFontCacheEntry::load(const std::string& path)
+{
+    if (path.empty() == true)
+    {
+        // Invalid path passed in.
+        return false;
+    }
+
+    // Try and open the file, check type and load width and height.
+    FILE* fp = fopen(path.c_str(), "r");
+    if (fp == NULL)
+    {
+        unload();
+        return false;
+    }
+    
+    int noChars = 0;
+       
+    // The first line contains the number of characters,
+    if (fscanf(fp, "%d", &noChars) != 1)
+    {
+        fclose(fp);
+        unload();
+        return false;
+    }
+    
+    // Store the path for later
+    _path = path;
+    
+    // Crete the correct size.
+    _chars.resize(noChars);
+      
+    // Now loop through loading in the values.
+    for (int i = 0; i < noChars; i++)
+    {   
+        int v = 0;
+        
+        // id.
+        fscanf(fp, "%d", &v);
+        _chars[i].id = v;
+        
+        // x.
+        fscanf(fp, "%d", &v);
+        _chars[i].x = v;
+
+        // y.
+        fscanf(fp, "%d", &v);
+        _chars[i].y = v;
+
+        // width.
+        fscanf(fp, "%d", &v);
+        _chars[i].width = v;
+
+        // height.
+        fscanf(fp, "%d", &v);
+        _chars[i].height = v;
+
+        // xoffset.
+        fscanf(fp, "%d", &v);
+        _chars[i].xOffset = v;
+
+        // yoffset.
+        fscanf(fp, "%d", &v);
+        _chars[i].yOffset = v;
+
+        // xAdvance.
+        fscanf(fp, "%d", &v);
+        _chars[i].xAdvance = v;
+    }
+    
+    fclose(fp);
+    
+    // Now change extension to fnb.
+    _path[_path.length()-1] = 'b';
+
+    _img.setMask(true);
+    if (_img.load(_path) == false)
+    {
+        unload();
+        return false;
+    }
+
+    _path[_path.length()-1] = 't';
+    
+    return true;
+}
+
+void EAFontCacheEntry::incReferences() 
+{ 
+    _refs++; 
+    
+    printf("References are now %d\r\n", _refs);
+}
+
+void EAFontCacheEntry::decReferences() 
+{ 
+    _refs--; 
+
+    printf("References are now %d\r\n", _refs);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fonts/EAFontCacheEntry.h	Mon Nov 01 13:07:40 2010 +0000
@@ -0,0 +1,44 @@
+// Copyright 2010 Richard Parker
+
+#ifndef MBED_EAFONTCACHEENTRY_H
+#define MBED_EAFONTCACHEENTRY_H
+
+#include "mbed.h"
+
+#include <string>
+#include <vector>
+
+#include "EAFont.h"
+#include "EAImage.h"
+
+/**
+ * Class to handle the font cache entries for the EA LCD.
+ * @author Richard Parker
+ */
+class EAFontCacheEntry
+{
+public:    
+    EAFontCacheEntry();
+    ~EAFontCacheEntry();
+  
+    bool load(const std::string& path);
+    void unload();
+    
+    inline const std::string& path() { return _path; }
+    inline int noChars() { return _chars.size(); }
+    inline const std::vector<EAFont::EACharacter>& chars() { return _chars; }
+    inline const EAImage& data() { return _img; }
+    inline int references() { return _refs; }
+    
+    void incReferences();
+    void decReferences();
+
+private:
+    std::vector<EAFont::EACharacter> _chars;
+    std::string _path;
+    int _refs;
+    EAImage _img;
+
+};
+
+#endif
\ No newline at end of file
--- a/graphics/EAFont.cpp	Thu May 06 23:32:14 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-// Copyright 2010 Richard Parker
-
-#include "mbed.h"
-#include "EAFont.h"
-
-#include "../screen/EALCD.h"
-
-EAFont::EAFont()
-:   _path(NULL),
-    _chars(NULL),
-    _noChars(0)
-{
-    _img.setCached(true);
-    _img.setMask(true);
-}
-
-EAFont::~EAFont()
-{
-    // Remember to free up allocated memory.
-    if (_chars != NULL)
-    {
-        delete[] _chars;
-        _chars = NULL;
-    }
-
-    if (_path != NULL)
-    {
-        delete[] _path;
-        _path = NULL;
-    }
-}
-
-bool EAFont::load(const char* path)
-{
-    if (path == NULL)
-    {
-        // Invalid path passed in.
-        return false;
-    }
-    
-    // Load font descriptor into look up table.  
-
-    // Try and open the file, check type and load width and height.
-    FILE* fp = fopen(path, "r");
-    if (fp == NULL)
-    {
-        return false;
-    }
-    
-    int noChars = 0;
-       
-    // The first line contains the number of characters,
-    if (fscanf(fp, "%d", &noChars) != 1)
-    {
-        fclose(fp);
-        return false;
-    }
-    
-    // Store the path for later
-    int pathLen = strlen(path);
-    
-    // If already loaded an image then clear to load the new one.
-    if (_path != NULL)
-    {
-        delete[] _path;
-        _path = NULL;
-    }
-    
-    // Now allocate enough space to hold path. Note +1 for null character.
-    _path = new char[pathLen+1];
-    
-    // Now copy over passed in path to path variable.
-    strcpy(_path, path);
-    
-    // Now change extension to fnb.
-    _path[pathLen-1] = 'b';
-    
-    _noChars = noChars;
-   
-    // Now that have the correct number of characters want to reserve enough space to hold. First
-    // check that there is not already memory allocated.
-    if (_chars != NULL)
-    {
-        delete[] _chars;
-    }       
-    
-    // Now create large enough array.
-    _chars = new EACharacter[noChars];
-    
-    // Now loop through loading in the values.
-    for (int i = 0; i < noChars; i++)
-    {   
-        int v = 0;
-        
-        // id.
-        fscanf(fp, "%d", &v);
-        _chars[i].id = v;
-        
-        // x.
-        fscanf(fp, "%d", &v);
-        _chars[i].x = v;
-
-        // y.
-        fscanf(fp, "%d", &v);
-        _chars[i].y = v;
-
-        // width.
-        fscanf(fp, "%d", &v);
-        _chars[i].width = v;
-
-        // height.
-        fscanf(fp, "%d", &v);
-        _chars[i].height = v;
-
-        // xoffset.
-        fscanf(fp, "%d", &v);
-        _chars[i].xOffset = v;
-
-        // yoffset.
-        fscanf(fp, "%d", &v);
-        _chars[i].yOffset = v;
-
-        // xAdvance.
-        fscanf(fp, "%d", &v);
-        _chars[i].xAdvance = v;
-    }
-    
-    fclose(fp);
-    
-    // Now load the cached image.
-    _img.load(_path);
-   
-    return true;    
-}
-
-bool EAFont::_getCharacter(char c, EACharacter& detail)
-{
-    for (int i = 0; i < _noChars; i++)
-    {
-        if (_chars[i].id == c)
-        {
-            detail = _chars[i];
-            return true;
-        }
-    }
-    
-    return false;
-}
--- a/graphics/EAFont.h	Thu May 06 23:32:14 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-// Copyright 2010 Richard Parker
-
-#ifndef MBED_EAFONT_H
-#define MBED_EAFONT_H
-
-#include "mbed.h"
-#include "../widgets/EAImage.h"
-
-class EALCD;
-
-/**
- * Class to handle the font for the EA LCD.
- * @author Richard Parker
- */
-class EAFont
-{
-public:
-    friend EALCD;
-    
-    struct EACharacter
-    {
-        unsigned char id;
-        unsigned char x;
-        unsigned char y;
-        unsigned char width;
-        unsigned char height;
-        unsigned char xOffset;
-        unsigned char yOffset;
-        unsigned char xAdvance;
-    };
-
-    EAFont();   
-    ~EAFont();
-    
-    inline const char* path() const { return _path; }
-    
-    inline bool isValid() const { return (_path != NULL); }
-    
-    bool load(const char* path);
-    
-    inline void setCached(bool value) { _img.setCached(value); }
-    inline bool isCached() { return _img.isCached(); }
-           
-private:
-    char* _path;
-    EACharacter* _chars;
-    int _noChars;
-    EAImage _img;
-
-    bool _getCharacter(char c, EACharacter& detail);
-    inline EAImage* _data() { return &_img; }
-    
-};
-
-#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/images/EAImage.cpp	Mon Nov 01 13:07:40 2010 +0000
@@ -0,0 +1,453 @@
+// Copyright 2010 Richard Parker
+
+#include "mbed.h"
+
+#include "EAImage.h"
+
+#include "../graphics/EAPen.h"
+#include "../graphics/EAColor.h"
+#include "../screen/EALCD.h"
+
+EAImage::EAImage()
+:   _path(NULL),
+    _palette(NULL),
+    _dataOffset(0),
+    _mask(false)
+{
+    // Start from known state.
+    unload();
+}
+
+EAImage::~EAImage()
+{
+    unload();
+}
+
+int EAImage::_feof(FILE* stream)
+{
+    return feof(stream);
+}
+
+
+int EAImage::_fseek(FILE* stream, long int offset, int origin)
+{
+    return fseek(stream, offset, origin);
+}
+
+size_t EAImage::_fread(void* ptr, size_t size, size_t count, FILE* stream)
+{
+    return fread(ptr, size, count, stream);
+}
+
+bool EAImage::_loadPalette(FILE* fp)
+{
+    // Can't do anything with a null pointer unless cached.
+    if (fp == NULL)
+    {
+        return false;
+    }
+    
+    // Clear any previously loaded palette.
+    if (_palette != NULL)
+    {
+        delete[] _palette;
+        _palette = NULL;
+    }
+    
+    // If the number of bits is not less than 16 then return after having cleared the 
+    // palette. There is no palette required.
+    if (info().bitsPerPixel >= 16)
+    {
+        return true;
+    }
+    
+    // First create a palette of the required size.
+    unsigned int noColors = info().noColors;
+    
+    // When 0 the number of colors is equal to 2^n where n is the bits per pixel.
+    if (noColors == 0)
+    {
+        noColors = pow((double)2, info().bitsPerPixel);
+    }
+    
+    // Create the palette and assign the memory.
+    _palette = new EAColor[noColors];
+    
+    // Now parse the palette. First seek to the start of the palette. This must be the 
+    // start of the bitmap data minus the number of colour entries multiplied by 4 (the
+    // colours are stored as 4 byte long entries, the last byte can be ignored).
+    unsigned int offset = _dataOffset - (noColors*4);
+    
+    // Seek to the start of the table.
+    _fseek(fp, offset, SEEK_SET);
+    unsigned char buffer[4];
+    
+    // Iterate through the table filling the palette as needed.
+    for (int i = 0; i < noColors; i++)
+    {
+        int sizeRead = _fread(&buffer, 4, 1, fp);
+        
+        if (sizeRead == 1)
+        {
+            _palette[i].setRgb(buffer[2], buffer[1], buffer[0]);
+        }
+    }
+    
+    return true;
+}
+
+bool EAImage::_loadHeader(const std::string& path)
+{
+    if (path.empty() == true)
+    {
+        // Invalid path passed in.
+        return false;
+    }
+    
+    // Try and open the file, check type and load width and height.
+    FILE* fp = fopen(path.c_str(), "r");
+    if (fp == NULL)
+    {
+        return false;
+    }
+
+    unsigned int bufint = 0;
+    unsigned int offset = 0;
+
+    // Read the magic numbers at start.
+    fread(&bufint, 1, 2, fp);   
+    if (bufint != 0x4d42)
+    {
+        // Clean up file handle.
+        fclose(fp);
+        unload();
+    
+        // Header incorrect.
+        return false;
+    }
+       
+    // Now read the bmp file size.
+    fread(&bufint, 1, 4, fp);
+      
+    // Now read the two creator values and throw away.
+    fread(&bufint, 1, 2, fp);
+    fread(&bufint, 1, 2, fp);
+    
+    // Now read the offset for the bitmap data.
+    fread(&bufint, 1, 4, fp);
+    offset = bufint;
+         
+    // Retrieve the header.
+    fread(&_header, sizeof(EABMPHeader), 1, fp);
+          
+    // Make sure the compression type is a value that can be dealt with. 
+    if ((info().compressionType != 3) && (info().compressionType != 0))
+    {      
+        // Clean up file handle.
+        fclose(fp);        
+        unload();
+    
+        // Header incorrect.
+        return false;
+    }
+    
+    // Set the values for later.
+    _dataOffset = offset;
+    setWidth(info().width);
+    setHeight(info().height);
+      
+    // If the bits per pixel are less than 16 then the bitmap is using a colour 
+    // palette which should be loaded first.
+    if (_loadPalette(fp) == false)
+    {
+        fclose(fp);
+        
+        return false;
+    }
+
+    // Close the file.
+    fclose(fp); 
+    
+    return true;
+}
+
+int EAImage::_wordsInRow()
+{
+    // If there were no padding to 32 bit boundaries this would be the number of bits per row 
+    // in the file.
+    int bitsPerWidth = width() * info().bitsPerPixel;
+       
+    // This is the row size with padding on the end.
+    int remainder = (bitsPerWidth % 32);
+    int bitsPerRow = (remainder == 0) ? bitsPerWidth : bitsPerWidth + (32 - remainder);
+    
+    // Return the size in number of words.
+    return (bitsPerRow / 32);
+}
+
+int EAImage::_wordForX(unsigned int x)
+{
+    int bitForX = x * info().bitsPerPixel;
+    
+    return (bitForX / 32);
+}
+
+int EAImage::_xWordOffset(unsigned int x)
+{
+    int bitForX = x * info().bitsPerPixel;
+    
+    return (bitForX % 32);
+}
+
+unsigned short EAImage::_getColourAtOffset(unsigned int word, int offset)
+{
+    // Sort bytes for endianness.
+    unsigned char* cptr;
+    unsigned short result = 0x0000;
+
+    // Now need to decide how to cast the value to a colour.
+    switch (info().bitsPerPixel)
+    {
+        // Swap the bytes around.
+        case 32:
+        case 4:
+        case 8:
+        case 1:
+            unsigned char tmp;
+            cptr = (unsigned char*)&word;
+            tmp = cptr[0];
+            cptr[0] = cptr[3];
+            cptr[3] = tmp;
+            tmp = cptr[1];
+            cptr[1] = cptr[2];
+            cptr[2] = tmp;
+        break;
+
+        default:
+        // Swap the 16bits around.
+        case 16:
+            unsigned char tmpa;
+            unsigned char tmpb;
+            cptr = (unsigned char*)&word;
+            tmpa = cptr[1];
+            tmpb = cptr[0];
+            cptr[1] = cptr[3];
+            cptr[0] = cptr[2];
+            cptr[3] = tmpa;
+            cptr[2] = tmpb;
+        break;
+    }
+
+    // First shift off the pixels above.
+    word = word << offset;
+    
+    // Now shift down so that pixel is in lsb.
+    word = word >> (32 - info().bitsPerPixel);
+
+    EAColor c;
+            
+    // Now need to decide how to cast the value to a colour.
+    switch (info().bitsPerPixel)
+    {
+        case 8:
+        case 4:
+        case 1:
+            if (_palette != NULL)
+            {
+                result = _palette[word].rawValue();
+            } else {
+                result = 0x0000;
+            }
+        break;
+
+        // By default just cast to unsigned short and return.        
+        default:
+        case 16:
+            result = (unsigned short)(word);
+        break;
+        
+        case 24:                        
+        case 32:         
+            unsigned char b = ((word << 0) >> 24);
+            unsigned char g = ((word << 8) >> 24);
+            unsigned char r = ((word << 16) >> 24);
+                       
+            c.setRgb(r, g, b);
+            result = c.rawValue();
+        break;
+    }
+    
+    return result;
+}
+
+bool EAImage::load(const std::string& path)
+{
+    if (path.empty() == true)
+    {
+        // Reset all of the state.
+        unload();
+
+        // Invalid path passed in.
+        return false;
+    }
+
+    if (_loadHeader(path) == false)
+    {
+        // Reset all of the state.
+        unload();
+
+        return false;
+    }
+
+    _path = path;
+       
+    // Image loaded successfully.
+    return true;
+}
+
+void EAImage::unload()
+{
+    // Empty the header struct.
+    _header.headerSize = 0;
+    _header.width = 0;
+    _header.height = 0;
+    _header.noColorPlanes = 0;
+    _header.bitsPerPixel = 0;
+    _header.compressionType = 0;
+    _header.bmpSize = 0;
+    _header.horizontalRes = 0;
+    _header.verticalRes = 0;
+    _header.noColors = 0;
+    _header.noImportantColors = 0;
+  
+    // Clear the palette.
+    if (_palette != NULL)
+    {
+        //delete[] _palette;
+        _palette = NULL;
+    }
+    
+    // Clear the path.
+    _path.clear();
+
+    // Clear the data offset.
+    _dataOffset = 0;
+    
+    // Set the size to 0.
+    setWidth(0);
+    setHeight(0);
+}
+
+void EAImage::paint(EALCD& lcd)
+{
+    paint(lcd, 0, 0, width(), height());
+}
+
+void EAImage::paint(EALCD& lcd, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
+{
+    if (isValid() == false)
+    {
+        return;
+    }
+
+    // Don't allow draw out of range.
+    if (x + w > width())
+    {
+        return;
+    }
+
+    if (y + h > height())
+    {
+        return;
+    }
+    
+    // Buffer to hold load one line at a time this must be large enough to hold all of the data used 
+    // for a line in the file. Note that the line in the file is padded so that it always ends on a 
+    // 32 bit boundary.
+    int wordsInRow = _wordsInRow();
+    unsigned int buffer[wordsInRow];
+    int xD = 0;
+    int yD = 0;
+    int wordOffset = 0;
+    int bitsPerPixel = info().bitsPerPixel;
+    unsigned short data = 0;
+    
+    // Try and open the file, skip straight to the data.
+    FILE* fp = NULL;
+    fp = fopen(_path.c_str(), "r");
+    if (fp == NULL)
+    {
+        return;
+    }
+           
+    // Skip the header and size.
+    _fseek(fp, _dataOffset, SEEK_SET);
+    
+    // Prepare the lcd for drawing.
+    lcd._window(this->x(), this->y(), w, h);
+    lcd._moveTo(this->x(), this->y()); 
+    
+    // Move in the file to the first pixel in the window.
+    _fseek(fp, (y*wordsInRow*4)+(_wordForX(x)*4), SEEK_CUR); 
+                            
+    // Now read the data.
+    while (!_feof(fp))
+    {    
+        wordOffset = _xWordOffset(x);
+               
+        int sizeRead = _fread(&buffer, 4, wordsInRow, fp);
+        
+        for (int i = 0; i < sizeRead; i++)
+        {        
+            while (wordOffset < 32)
+            {           
+                // Convert the colour to a 16 bit colour value that can be written directly to the screen.                
+                data = _getColourAtOffset(buffer[i], wordOffset);
+                
+                if (isMask() == true)
+                {
+                    // When a mask the 0x0000 value is transparent anything else is drawn with the pen color.
+                    if (data == 0x0000)
+                    {
+                        lcd.noop();
+                    } else {
+                        lcd._writeToDisplay(lcd.pen().color().rawValue());
+                    }
+                } else {                    
+                    // Not a mask so just use colour that have loaded.
+                    lcd._writeToDisplay(data);
+                }
+                
+                // Got to next pixel in the word.
+                wordOffset += bitsPerPixel;
+
+                // Keep count of current x value.
+                xD++;
+                if (xD == w)
+                {
+                    break;
+                }            
+            }
+            wordOffset = 0;
+            
+            // When written all required pixels exit.
+            if (xD == w)
+            {
+                xD = 0;
+                break;
+            }            
+        }
+
+        // Keep count of curernt y value.
+        yD++;
+        if (yD == h)
+        {
+            break;
+        }            
+    }
+    
+    // Close the file and release handle.
+    fclose(fp);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/images/EAImage.h	Mon Nov 01 13:07:40 2010 +0000
@@ -0,0 +1,73 @@
+// Copyright 2010 Richard Parker
+
+#ifndef MBED_EAIMAGE_H
+#define MBED_EAIMAGE_H
+
+#include "mbed.h"
+#include <string>
+
+#include "EAWidget.h"
+
+class EALCD;
+class EAColor;
+
+/**
+ * Class to handle loading and displaying an image.
+ * @author Richard Parker
+ */
+class EAImage: public EAWidget
+{
+public:
+    struct EABMPHeader {
+        unsigned int headerSize;
+        unsigned int width;
+        unsigned int height;
+        unsigned short noColorPlanes;
+        unsigned short bitsPerPixel;
+        unsigned int compressionType;
+        unsigned int bmpSize;
+        unsigned int horizontalRes;
+        unsigned int verticalRes;
+        unsigned int noColors;
+        unsigned int noImportantColors;
+    };
+    
+    EAImage();
+    ~EAImage();
+    
+    bool load(const std::string& path);
+    void unload();
+    
+    inline const std::string& path() const { return _path; }
+    
+    inline bool isValid() const { return (_path.empty() == false); }
+    
+    virtual void paint(EALCD& lcd);
+    virtual void paint(EALCD& lcd, unsigned int x, unsigned int y, unsigned int w, unsigned int h);
+    
+    inline const EABMPHeader& info() { return _header; }
+    
+    inline bool isMask() { return _mask; }
+    inline void setMask(bool value) { _mask = value; }
+    
+private:
+    std::string _path;
+    EAColor* _palette;
+    unsigned int _dataOffset;
+    EABMPHeader _header;
+    bool _mask;
+    
+    bool _loadHeader(const string& path);
+    bool _loadPalette(FILE* fp);
+    
+    int _wordsInRow();
+    int _wordForX(unsigned int x);
+    int _xWordOffset(unsigned int x);
+    unsigned short _getColourAtOffset(unsigned int word, int offset);
+    
+    int _fseek(FILE* stream, long int offset, int origin);
+    size_t _fread(void* ptr, size_t size, size_t count, FILE* stream);
+    int _feof(FILE* stream);
+};
+
+#endif
\ No newline at end of file
--- a/manager/EATouchManager.cpp	Thu May 06 23:32:14 2010 +0000
+++ b/manager/EATouchManager.cpp	Mon Nov 01 13:07:40 2010 +0000
@@ -10,7 +10,7 @@
     _lcd(lcd),
     _head(NULL),
     _count(0),
-    _timeout(200)
+    _timeout(2000)
 {
 }
 
--- a/screen/EALCD.cpp	Thu May 06 23:32:14 2010 +0000
+++ b/screen/EALCD.cpp	Mon Nov 01 13:07:40 2010 +0000
@@ -598,24 +598,34 @@
     img.paint(*this);
 }
 
-void EALCD::drawText(unsigned short x, unsigned short y, char* text)
+void EALCD::drawText(unsigned short x, unsigned short y, const std::string& text)
 {
+    printf("Draw text.\r\n");
+
     // Don't try painting with an invalid font or no text
-    if ((_font.isValid() == false) || (text == NULL))
+    if ((_font.isValid() == false) || (text.empty() == true))
     {
+        printf("Failed to load valid font.\r\n");
         return;
     }
     
-    EAImage* img = _font._data();
+    EAImage img;
+    
+    if (_font._data(img) == false)
+    {
+        printf("Failed to load data.\r\n");
+        return;
+    }
+    
     EAFont::EACharacter detail;
       
-    for (int i = 0; i < strlen(text); i++)
+    for (int i = 0; i < text.length(); i++)
     {
         if (_font._getCharacter(text[i], detail) == true)
         {
-            img->setX(x+detail.xOffset);
-            img->setY(y+detail.yOffset);
-            img->paint(*this, detail.x, detail.y, detail.width, detail.height);       
+            img.setX(x+detail.xOffset);
+            img.setY(y+detail.yOffset);
+            img.paint(*this, detail.x, detail.y, detail.width, detail.height);       
             
             x += detail.xAdvance;
         } else {
--- a/screen/EALCD.h	Thu May 06 23:32:14 2010 +0000
+++ b/screen/EALCD.h	Mon Nov 01 13:07:40 2010 +0000
@@ -7,8 +7,8 @@
 
 #include "../graphics/EAPen.h"
 #include "../graphics/EABrush.h"
-#include "../graphics/EAFont.h"
-#include "../widgets/EAImage.h"
+#include "../fonts/EAFont.h"
+#include "../images/EAImage.h"
 
 #ifndef PI
 #define PI 3.14593
@@ -56,7 +56,7 @@
     void drawEllipse(short x, short y, unsigned short w, unsigned short h);
     void drawFilledEllipse(short x, short y, unsigned short w, unsigned short h);
     void drawImage(unsigned short x, unsigned short y, EAImage& img);
-    void drawText(unsigned short x, unsigned short y, char* text); 
+    void drawText(unsigned short x, unsigned short y, const std::string& text); 
     
     inline unsigned short width() const { return 320; }
     inline unsigned short height() const { return 240; }
--- a/widgets/EAButton.cpp	Thu May 06 23:32:14 2010 +0000
+++ b/widgets/EAButton.cpp	Mon Nov 01 13:07:40 2010 +0000
@@ -39,47 +39,21 @@
     {
         _manager.deleteHitBox(_box);
         _box = NULL;
-    }
-    
-    if (_text != NULL)
-    {
-        delete[] _text;
-        _text = NULL;
-    }    
+    }   
 }
 
 void EAButton::paint(EALCD& lcd)
 {
     lcd.drawFilledRect(x(), y(), width(), height());
-    if (_text != NULL)
+    if (_text.empty() == false)
     {
         lcd.drawText(x()+10, y()+10, _text);
     }
 }
 
-bool EAButton::setText(char* text)
-{
-    if (text == NULL)
-    {
-        // Invalid text passed in.
-        return false;
-    }
-    
-    // Store the text for later
-    int textLen = strlen(text);
-    
-    // If already have some text then clear to load the new text.
-    if (_text != NULL)
-    {
-        delete[] _text;
-        _text = NULL;
-    }
-    
-    // Now allocate enough space to hold text. Note +1 for null character.
-    _text = new char[textLen+1];
-    
-    // Now copy over passed in text to text variable.
-    strcpy(_text, text);
+bool EAButton::setText(const std::string& text)
+{   
+    _text = text;
     
     return true;
 }
--- a/widgets/EAButton.h	Thu May 06 23:32:14 2010 +0000
+++ b/widgets/EAButton.h	Mon Nov 01 13:07:40 2010 +0000
@@ -4,6 +4,7 @@
 #define MBED_EABUTTON_H
 
 #include "mbed.h"
+#include <string>
 
 #include "EAWidget.h"
 
@@ -31,8 +32,8 @@
     
     virtual void paint(EALCD& lcd);
     
-    bool setText(char* text);
-    inline const char* text() const { return _text; }
+    bool setText(const std::string& text);
+    inline const string& text() const { return _text; }
 
     EAHitHandler* handler() const;
     void setHandler(EAHitHandler* handler);
@@ -52,7 +53,7 @@
     EATouchManager& _manager;
     EAHitBox* _box;
     
-    char* _text;
+   std::string _text;
     
     void _updateHitBox();
 };
--- a/widgets/EACompass.cpp	Thu May 06 23:32:14 2010 +0000
+++ b/widgets/EACompass.cpp	Mon Nov 01 13:07:40 2010 +0000
@@ -32,6 +32,9 @@
     
     // Now draw the pointer.
     _drawPointer(lcd);
+    
+    // Next draw the angle value.
+    _drawAngle(lcd);
 }
 
 void EACompass::update(EALCD& lcd, float angle)
@@ -45,6 +48,7 @@
     lcd.setPen(p);    
 
     _drawPointer(lcd);
+    _drawAngle(lcd);
     
     p.setColor(oldColour);
     lcd.setPen(p);
@@ -53,6 +57,7 @@
     setAngle(angle);
     
     _drawPointer(lcd);
+    _drawAngle(lcd);
 }
 
 void EACompass::_drawPointer(EALCD& lcd)
@@ -73,3 +78,24 @@
     // Draw ball at north end.
     lcd.drawFilledEllipse(x1-5, y1-5, 10, 10);
 }
+
+void EACompass::_drawAngle(EALCD& lcd)
+{
+    short tx = x() + (diameter()/2);
+    short ty = y() + diameter();
+
+    EAFont font;
+    
+    font.load("/local/small.fnt");   
+    lcd.setFont(font);  
+
+    /*
+    REVISIT - formatting string to draw heading.
+    char angleBuffer[5];
+    float angleDeg = (angle() * 180)/PI;
+    sprintf(angleBuffer, "%03.0f", angleDeg);
+    
+    lcd.drawText(tx, ty, angleBuffer);
+    */
+    
+}
--- a/widgets/EACompass.h	Thu May 06 23:32:14 2010 +0000
+++ b/widgets/EACompass.h	Mon Nov 01 13:07:40 2010 +0000
@@ -40,6 +40,7 @@
     unsigned short _diameter;
            
     void _drawPointer(EALCD& lcd);
+    void _drawAngle(EALCD& lcd);
     
 };
 
--- a/widgets/EAImage.cpp	Thu May 06 23:32:14 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,647 +0,0 @@
-// Copyright 2010 Richard Parker
-
-#include "mbed.h"
-
-#include "EAImage.h"
-
-#include "../graphics/EAPen.h"
-#include "../graphics/EAColor.h"
-#include "../screen/EALCD.h"
-
-EAImage::EAImage()
-:   _path(NULL),
-    _palette(NULL),
-    _dataOffset(0),
-    _mask(false),
-    _cached(false),
-    _cache(NULL),
-    _size(0L),
-    _pos(0L)
-{
-    // Start from known state.
-    unload();
-}
-
-EAImage::~EAImage()
-{
-    unload();
-}
-
-int EAImage::_feof(FILE* stream)
-{
-    if (isCached() == true)
-    {
-        return (_pos < _size) ? 0 : 1;
-    } else {
-        return feof(stream);
-    }
-}
-
-
-int EAImage::_fseek(FILE* stream, long int offset, int origin)
-{
-    if (isCached() == true)
-    {   
-        switch (origin)
-        {
-            default:
-            case SEEK_SET:
-                _pos = offset;
-            break;
-            case SEEK_CUR:
-                _pos = _pos + offset;
-            break;
-            case SEEK_END:
-                _pos = (_size-1) + offset;
-            break;
-        }
-        
-        // Make sure position within range.
-        if (_pos < 0)
-        {
-            _pos = 0;
-            return 0;
-        }
-        
-        if (_pos > (_size-1))
-        {
-            _pos = (_size-1);
-            return 0;
-        }
-        
-        // Error.
-        return 1;
-    } else {
-        return fseek(stream, offset, origin);
-    }
-}
-
-size_t EAImage::_fread(void* ptr, size_t size, size_t count, FILE* stream)
-{
-    if (isCached() == true)
-    {
-        // Truncate size to fit array if needed.
-        if (_pos + (count*size) > _size)
-        {
-            count = (_size - _pos)/size;
-        }
-        
-        if (count <= 0)
-        {
-            return 0;
-        }
-        
-        // Now copy out of cache to array.
-        memcpy(ptr, &_cache[_pos], count*size);
-        
-        // Update the file position.
-        _pos = _pos + (count*size);
-        
-        // Return the number of bytes read.
-        return count;
-    } else {
-        return fread(ptr, size, count, stream);
-    }
-}
-
-bool EAImage::_loadCache(FILE* fp)
-{
-    // Can't do anything with a null pointer.
-    if (fp == NULL)
-    {
-        return false;
-    }
-    
-    // Clear any previously loaded cache.
-    if (_cache != NULL)
-    {
-        delete[] _cache;
-        _cache = NULL;
-    }
-    _size = 0L;
-    _pos = 0L;
-
-    if (isCached() == false)
-    {
-        return true;
-    }
-
-    // Get the size of the file.    
-    fseek(fp, 0, SEEK_END);
-    long int size = ftell(fp);
-    
-    if (size == -1)
-    {
-        // Something went wronmg with the command.
-        return false;
-    }
-
-    // Now create a cache large enough to hold all of the image data.
-    _cache = new char[size];
-    
-    if (_cache == NULL)
-    {
-        // Unable to allocate enough space for the font.
-        return false;
-    }
-
-    // Now rewind file pointer back to the beginning.
-    rewind(fp);
-    
-    const unsigned int CHUNK_SIZE = 100;
-    long int sizeRead = 0;
-    long int totalSizeRead = 0;
-        
-    // Load in small chunks at a time.
-    while (!feof(fp))
-    {
-        // Read into the buffer.
-        sizeRead = fread(&_cache[totalSizeRead], 1, CHUNK_SIZE, fp);
-                        
-        // Update total count of amount of data loaded.
-        totalSizeRead += sizeRead;
-    }
-    
-    // Check that the whole file loaded.
-    if (totalSizeRead != size)
-    {
-        // Clear cache.        
-        delete[] _cache;
-        _cache = NULL;
-        
-        // Return error.
-        return false;
-    }
-    
-    // Record size and position.
-    _size = size;
-    _pos = 0L;
-    
-    return true;
-}
-
-bool EAImage::_loadPalette(FILE* fp)
-{
-    // Can't do anything with a null pointer unless cached.
-    if ((fp == NULL) && (isCached() == false))
-    {
-        return false;
-    }
-    
-    // Clear any previously loaded palette.
-    if (_palette != NULL)
-    {
-        delete[] _palette;
-        _palette = NULL;
-    }
-    
-    // If the number of bits is not less than 16 then return after having cleared the 
-    // palette. There is no palette required.
-    if (info().bitsPerPixel >= 16)
-    {
-        return true;
-    }
-    
-    // First create a palette of the required size.
-    unsigned int noColors = info().noColors;
-    
-    // When 0 the number of colors is equal to 2^n where n is the bits per pixel.
-    if (noColors == 0)
-    {
-        noColors = pow((double)2, info().bitsPerPixel);
-    }
-    
-    // Create the palette and assign the memory.
-    _palette = new EAColor[noColors];
-    
-    // Now parse the palette. First seek to the start of the palette. This must be the 
-    // start of the bitmap data minus the number of colour entries multiplied by 4 (the
-    // colours are stored as 4 byte long entries, the last byte can be ignored).
-    unsigned int offset = _dataOffset - (noColors*4);
-    
-    // Seek to the start of the table.
-    _fseek(fp, offset, SEEK_SET);
-    unsigned char buffer[4];
-    
-    // Iterate through the table filling the palette as needed.
-    for (int i = 0; i < noColors; i++)
-    {
-        int sizeRead = _fread(&buffer, 4, 1, fp);
-        
-        if (sizeRead == 1)
-        {
-            _palette[i].setRgb(buffer[2], buffer[1], buffer[0]);
-        }
-    }
-    
-    return true;
-}
-
-bool EAImage::_loadHeader(const char* path)
-{
-    if (path == NULL)
-    {
-        // Invalid path passed in.
-        return false;
-    }
-    
-    // Try and open the file, check type and load width and height.
-    FILE* fp = fopen(path, "r");
-    if (fp == NULL)
-    {
-        return false;
-    }
-
-    unsigned int bufint = 0;
-    unsigned int offset = 0;
-
-    // Read the magic numbers at start.
-    fread(&bufint, 1, 2, fp);   
-    if (bufint != 0x4d42)
-    {
-        // Clean up file handle.
-        fclose(fp);
-        unload();
-    
-        // Header incorrect.
-        return false;
-    }
-       
-    // Now read the bmp file size.
-    fread(&bufint, 1, 4, fp);
-      
-    // Now read the two creator values and throw away.
-    fread(&bufint, 1, 2, fp);
-    fread(&bufint, 1, 2, fp);
-    
-    // Now read the offset for the bitmap data.
-    fread(&bufint, 1, 4, fp);
-    offset = bufint;
-         
-    // Retrieve the header.
-    fread(&_header, sizeof(EABMPHeader), 1, fp);
-          
-    // Make sure the compression type is a value that can be dealt with. 
-    if ((info().compressionType != 3) && (info().compressionType != 0))
-    {      
-        // Clean up file handle.
-        fclose(fp);        
-        unload();
-    
-        // Header incorrect.
-        return false;
-    }
-    
-    // Set the values for later.
-    _dataOffset = offset;
-    setWidth(info().width);
-    setHeight(info().height);
-    
-    // If the image is to be cached then load the cache.
-    if (_loadCache(fp) == false)
-    {
-        // Clean up file handle.
-        fclose(fp);        
-        unload();
-    
-        // Header incorrect.
-        return false;
-    }
-             
-    // Close the file.
-    fclose(fp);
-    
-    return true;
-}
-
-int EAImage::_wordsInRow()
-{
-    // If there were no padding to 32 bit boundaries this would be the number of bits per row 
-    // in the file.
-    int bitsPerWidth = width() * info().bitsPerPixel;
-       
-    // This is the row size with padding on the end.
-    int remainder = (bitsPerWidth % 32);
-    int bitsPerRow = (remainder == 0) ? bitsPerWidth : bitsPerWidth + (32 - remainder);
-    
-    // Return the size in number of words.
-    return (bitsPerRow / 32);
-}
-
-int EAImage::_wordForX(unsigned int x)
-{
-    int bitForX = x * info().bitsPerPixel;
-    
-    return (bitForX / 32);
-}
-
-int EAImage::_xWordOffset(unsigned int x)
-{
-    int bitForX = x * info().bitsPerPixel;
-    
-    return (bitForX % 32);
-}
-
-unsigned short EAImage::_getColourAtOffset(unsigned int word, int offset)
-{
-    // Sort bytes for endianness.
-    unsigned char* cptr;
-    unsigned short result = 0x0000;
-
-    // Now need to decide how to cast the value to a colour.
-    switch (info().bitsPerPixel)
-    {
-        // Swap the bytes around.
-        case 32:
-        case 4:
-        case 8:
-        case 1:
-            unsigned char tmp;
-            cptr = (unsigned char*)&word;
-            tmp = cptr[0];
-            cptr[0] = cptr[3];
-            cptr[3] = tmp;
-            tmp = cptr[1];
-            cptr[1] = cptr[2];
-            cptr[2] = tmp;
-        break;
-
-        default:
-        // Swap the 16bits around.
-        case 16:
-            unsigned char tmpa;
-            unsigned char tmpb;
-            cptr = (unsigned char*)&word;
-            tmpa = cptr[1];
-            tmpb = cptr[0];
-            cptr[1] = cptr[3];
-            cptr[0] = cptr[2];
-            cptr[3] = tmpa;
-            cptr[2] = tmpb;
-        break;
-    }
-
-    // First shift off the pixels above.
-    word = word << offset;
-    
-    // Now shift down so that pixel is in lsb.
-    word = word >> (32 - info().bitsPerPixel);
-
-    EAColor c;
-            
-    // Now need to decide how to cast the value to a colour.
-    switch (info().bitsPerPixel)
-    {
-        case 8:
-        case 4:
-        case 1:
-            if (_palette != NULL)
-            {
-                result = _palette[word].rawValue();
-            } else {
-                result = 0x0000;
-            }
-        break;
-
-        // By default just cast to unsigned short and return.        
-        default:
-        case 16:
-            result = (unsigned short)(word);
-        break;
-        
-        case 24:                        
-        case 32:         
-            unsigned char b = ((word << 0) >> 24);
-            unsigned char g = ((word << 8) >> 24);
-            unsigned char r = ((word << 16) >> 24);
-                       
-            c.setRgb(r, g, b);
-            result = c.rawValue();
-        break;
-    }
-    
-    return result;
-}
-
-bool EAImage::load(const char* path)
-{
-    if (path == NULL)
-    {
-        // Reset all of the state.
-        unload();
-
-        // Invalid path passed in.
-        return false;
-    }
-
-    if (_loadHeader(path) == false)
-    {
-        // Reset all of the state.
-        unload();
-
-        return false;
-    }
-
-    int pathLen = strlen(path);
-    
-    // If already loaded an image then clear to load the new one.
-    if (_path != NULL)
-    {
-        delete[] _path;
-        _path = NULL;
-    }
-    
-    // Now allocate enough space to hold path. Note +1 for null character.
-    _path = new char[pathLen+1];
-    
-    // Now copy over passed in path to path variable.
-    strcpy(_path, path);
-    
-    // Image loaded successfully.
-    return true;
-}
-
-void EAImage::unload()
-{
-    // Empty the header struct.
-    _header.headerSize = 0;
-    _header.width = 0;
-    _header.height = 0;
-    _header.noColorPlanes = 0;
-    _header.bitsPerPixel = 0;
-    _header.compressionType = 0;
-    _header.bmpSize = 0;
-    _header.horizontalRes = 0;
-    _header.verticalRes = 0;
-    _header.noColors = 0;
-    _header.noImportantColors = 0;
-
-    // Clear the path.
-    if (_path != NULL)
-    {
-        delete[] _path;
-        _path = NULL;
-    }
-    
-    // Clear the palette.
-    if (_palette != NULL)
-    {
-        delete[] _palette;
-        _palette = NULL;
-    }
-
-    // Clear the data offset.
-    _dataOffset = 0;
-    
-    // Set the size to 0.
-    setWidth(0);
-    setHeight(0);
-    
-    // Empty the cache.
-    if (_cache != NULL)
-    {
-        delete[] _cache;
-        _cache = NULL;
-    }    
-    _size = 0L;
-    _pos = 0L;
-}
-
-void EAImage::paint(EALCD& lcd)
-{
-    paint(lcd, 0, 0, width(), height());
-}
-
-void EAImage::paint(EALCD& lcd, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
-{
-    if (isValid() == false)
-    {
-        return;
-    }
-    
-    // Don't allow draw out of range.
-    if (x + w > width())
-    {
-        return;
-    }
-
-    if (y + h > height())
-    {
-        return;
-    }
-    
-    // Buffer to hold load one line at a time this must be large enough to hold all of the data used 
-    // for a line in the file. Note that the line in the file is padded so that it always ends on a 
-    // 32 bit boundary.
-    int wordsInRow = _wordsInRow();
-    unsigned int buffer[wordsInRow];
-    int xD = 0;
-    int yD = 0;
-    int wordOffset = 0;
-    int bitsPerPixel = info().bitsPerPixel;
-    unsigned short data = 0;
-    
-    // Try and open the file, skip straight to the data.
-    FILE* fp = NULL;
-    if (isCached() == false)
-    {
-        fp = fopen(_path, "r");
-        if (fp == NULL)
-        {
-            return;
-        }
-    }
-        
-    // If the bits per pixel are less than 16 then the bitmap is using a colour 
-    // palette which should be loaded first.
-    if (_loadPalette(fp) == false)
-    {
-        if (isCached() == false)
-        {
-            fclose(fp);
-        }
-        
-        return;
-    }
-    
-    // Skip the header and size.
-    _fseek(fp, _dataOffset, SEEK_SET);
-    
-    // Prepare the lcd for drawing.
-    lcd._window(this->x(), this->y(), w, h);
-    lcd._moveTo(this->x(), this->y()); 
-    
-    // Move in the file to the first pixel in the window.
-    _fseek(fp, (y*wordsInRow*4)+(_wordForX(x)*4), SEEK_CUR); 
-                            
-    // Now read the data.
-    while (!_feof(fp))
-    {    
-        wordOffset = _xWordOffset(x);
-               
-        int sizeRead = _fread(&buffer, 4, wordsInRow, fp);
-        
-        for (int i = 0; i < sizeRead; i++)
-        {        
-            while (wordOffset < 32)
-            {           
-                // Convert the colour to a 16 bit colour value that can be written directly to the screen.                
-                data = _getColourAtOffset(buffer[i], wordOffset);
-                
-                if (isMask() == true)
-                {
-                    // When a mask the 0x0000 value is transparent anything else is drawn with the pen color.
-                    if (data == 0x0000)
-                    {
-                        lcd.noop();
-                    } else {
-                        lcd._writeToDisplay(lcd.pen().color().rawValue());
-                    }
-                } else {                    
-                    // Not a mask so just use colour that have loaded.
-                    lcd._writeToDisplay(data);
-                }
-                
-                // Got to next pixel in the word.
-                wordOffset += bitsPerPixel;
-
-                // Keep count of current x value.
-                xD++;
-                if (xD == w)
-                {
-                    break;
-                }            
-            }
-            wordOffset = 0;
-            
-            // When written all required pixels exit.
-            if (xD == w)
-            {
-                xD = 0;
-                break;
-            }            
-        }
-
-        // Keep count of curernt y value.
-        yD++;
-        if (yD == h)
-        {
-            break;
-        }            
-    }
-    
-    // Clear the palette.
-    if (_palette != NULL)
-    {
-        delete[] _palette;
-        _palette = NULL;
-    }
-    
-    if (isCached() == false)
-    {
-        // Close the file and release handle.
-        fclose(fp);
-    }
-}
-
-
--- a/widgets/EAImage.h	Thu May 06 23:32:14 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-// Copyright 2010 Richard Parker
-
-#ifndef MBED_EAIMAGE_H
-#define MBED_EAIMAGE_H
-
-#include "mbed.h"
-
-#include "EAWidget.h"
-
-class EALCD;
-class EAColor;
-
-/**
- * Class to handle loading and displaying an image.
- * @author Richard Parker
- */
-class EAImage: public EAWidget
-{
-public:
-    struct EABMPHeader {
-        unsigned int headerSize;
-        unsigned int width;
-        unsigned int height;
-        unsigned short noColorPlanes;
-        unsigned short bitsPerPixel;
-        unsigned int compressionType;
-        unsigned int bmpSize;
-        unsigned int horizontalRes;
-        unsigned int verticalRes;
-        unsigned int noColors;
-        unsigned int noImportantColors;
-    };
-    
-    EAImage();
-    ~EAImage();
-    
-    bool load(const char* path);
-    void unload();
-    
-    inline const char* path() const { return _path; }
-    
-    inline bool isValid() const { return (_path != NULL); }
-    
-    virtual void paint(EALCD& lcd);
-    virtual void paint(EALCD& lcd, unsigned int x, unsigned int y, unsigned int w, unsigned int h);
-    
-    inline const EABMPHeader& info() { return _header; }
-    
-    inline bool isMask() { return _mask; }
-    inline void setMask(bool value) { _mask = value; }
-    
-    inline bool isCached() { return _cached; }
-    inline void setCached(bool value) { _cached = value; }
-
-private:
-    char* _path;
-    EAColor* _palette;
-    unsigned int _dataOffset;
-    EABMPHeader _header;
-    bool _mask;
-    bool _cached;
-    char* _cache;
-    long int _size;
-    long int _pos;
-    
-    bool _loadHeader(const char* path);
-    bool _loadCache(FILE* fp);
-    bool _loadPalette(FILE* fp);
-    
-    int _wordsInRow();
-    int _wordForX(unsigned int x);
-    int _xWordOffset(unsigned int x);
-    unsigned short _getColourAtOffset(unsigned int word, int offset);
-    
-    int _fseek(FILE* stream, long int offset, int origin);
-    size_t _fread(void* ptr, size_t size, size_t count, FILE* stream);
-    int _feof(FILE* stream);
-};
-
-#endif
\ No newline at end of file