Index: themes/themes.pro
===================================================================
--- themes/themes.pro	(revision 7651)
+++ themes/themes.pro	(working copy)
@@ -9,7 +9,8 @@
 !macx:QMAKE_COPY_DIR = sh ./cpsvndir
 
 themes.path = $${PREFIX}/share/mythtv/themes/
-themes.files = blue defaultosd blueosd oldosd default G.A.N.T. classic DVR
+themes.files = blue default G.A.N.T. classic DVR 
+themes.files += defaultosd blueosd oldosd xvmcosd
 
 fonts.path = $${PREFIX}/share/mythtv
 fonts.files = FreeSans.ttf FreeMono.ttf
Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.cpp	(revision 7663)
+++ libs/libmythtv/NuppelVideoPlayer.cpp	(working copy)
@@ -1903,7 +1903,7 @@
                       visible.width(), visible.height());
 
         if (kCodec_NORMAL_END < GetDecoder()->GetVideoCodecID() &&
-            kCodec_SPECIAL_END > GetDecoder()->GetVideoCodecID() &&
+            kCodec_STD_XVMC_END > GetDecoder()->GetVideoCodecID() &&
             (600 < video_height))
         {            
             osd->DisableFade();
Index: libs/libmythtv/osd.h
===================================================================
--- libs/libmythtv/osd.h	(revision 7651)
+++ libs/libmythtv/osd.h	(working copy)
@@ -123,6 +123,12 @@
 
     void DisableFade(void);
 
+    bool HasPalette(void)         const { return hasPalette; }
+
+// TODO using a QValueList here is NOT threadsafe -- dtk
+    QValueList<QColor> GetPalette(void) const
+        { return surfPalette; }
+
  private:
     void SetDefaults();
     TTFFont *LoadFont(QString name, int size); 
@@ -149,6 +155,7 @@
     void parsePositionRects(OSDSet *container, QDomElement &element);
     void parsePositionImage(OSDSet *container, QDomElement &element);
     void parseListTree(OSDSet *container, QDomElement &element);
+    void parsePalette(QDomElement &element);
 
     int vid_width;
     int vid_height;
@@ -184,6 +191,12 @@
 
     OSDListTreeType *runningTreeMenu;
     QString treeMenuContainer;
+
+    // variables to support restricted color palette
+    bool               hasPalette;
+    QString            surftype;
+    QValueList<QColor> surfPalette;
+
 };
     
 #endif
Index: libs/libmythtv/osdtypes.cpp
===================================================================
--- libs/libmythtv/osdtypes.cpp	(revision 7651)
+++ libs/libmythtv/osdtypes.cpp	(working copy)
@@ -14,6 +14,14 @@
 
 #include "mythcontext.h"
 
+#include <sys/time.h>
+
+#ifdef TIMING
+#include "timer.h"
+#endif
+
+QValueList<QColor> OSDTypeImage::s_palette;
+
 OSDSet::OSDSet(const QString &name, bool cache, int screenwidth, 
                int screenheight, float wmult, float hmult, int frint)
       : QObject()
@@ -367,6 +375,10 @@
 
 void OSDSet::Draw(OSDSurface *surface, bool actuallydraw)
 {
+#ifdef TIMING
+Timer t("OSDSet::Draw");
+#endif
+
     if (actuallydraw)
     {
         vector<OSDType *>::iterator i = allTypes->begin();
@@ -443,7 +455,7 @@
 
 OSDTypeText::OSDTypeText(const QString &name, TTFFont *font, 
                          const QString &text, QRect displayrect)
-           : OSDType(name)
+           : OSDType(name), m_raster(0)
 {
     m_message = text;
     m_default_msg = text;
@@ -463,10 +475,13 @@
     m_scrollinit = false;
 
     m_linespacing = 1.5;
+
+    m_message.replace(QRegExp("%BR%"), "\n");
+    m_message.replace(QRegExp("\n")," \n ");
 }
 
 OSDTypeText::OSDTypeText(const OSDTypeText &other)
-           : OSDType(other.m_name)
+           : OSDType(other.m_name), m_raster(0)
 {
     m_displaysize = other.m_displaysize;
     m_screensize = other.m_screensize;
@@ -486,6 +501,11 @@
 
 OSDTypeText::~OSDTypeText()
 {
+    if (m_raster)
+    {
+       TTFFont::destroy_font_raster(m_raster);
+       m_raster=0;
+    }
 }
 
 void OSDTypeText::SetAltFont(TTFFont *font)
@@ -495,19 +515,43 @@
 
 void OSDTypeText::SetText(const QString &text)
 {
+    if (m_raster)
+    {
+       TTFFont::destroy_font_raster(m_raster);
+       m_raster=0;
+    }
+
     m_message = text;
     m_scrollinit = false;
+
+   m_message.replace(QRegExp("%BR%"), "\n");
+   m_message.replace(QRegExp("\n"), " \n ");
 }
 
 void OSDTypeText::SetDefaultText(const QString &text)
 {
+    if (m_raster)
+    {
+       TTFFont::destroy_font_raster(m_raster);
+       m_raster=0;
+    }
+
     m_message = text;
     m_default_msg = text;
     m_scrollinit = false;
+
+    m_message.replace(QRegExp("%BR%"), "\n");
+    m_message.replace(QRegExp("\n"), " \n ");
 }
 
 void OSDTypeText::Reinit(float wchange, float hchange)
 {
+    if (m_raster)
+    {
+       TTFFont::destroy_font_raster(m_raster);
+       m_raster=0;
+    }
+
     int width = (int)(m_screensize.width() * wchange);
     int height = (int)(m_screensize.height() * hchange);
     int x = (int)(m_screensize.x() * wchange);
@@ -519,6 +563,9 @@
 void OSDTypeText::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, 
                        int yoff)
 {
+#ifdef TIMING
+    Timer t("OSDTypeText::Draw");
+#endif
     int textlength = 0;
 
     if (m_message == QString::null)
@@ -530,17 +577,17 @@
     if (m_scroller)
         m_parent->SetDrawEveryFrame(true);
 
-    m_font->CalcWidth(m_message, &textlength);
+//    m_font->CalcWidth(m_message, &textlength);
 
     int maxlength = m_displaysize.width();
 
     if (m_multiline)
     {
-        QString tmp_msg = m_message;
-        tmp_msg.replace(QRegExp("%BR%"), "\n");
-        tmp_msg.replace(QRegExp("\n")," \n ");
+//        QString tmp_msg = m_message;
+//        tmp_msg.replace(QRegExp("%BR%"), "\n");
+//        tmp_msg.replace(QRegExp("\n"), " \n ");
 
-        QStringList wordlist = QStringList::split(" ", tmp_msg);
+        QStringList wordlist = QStringList::split(" ", m_message);
         int length = 0;
         int lines = 0;
 
@@ -658,6 +705,10 @@
                              const QString &text, int fade, int maxfade, 
                              int xoff, int yoff)
 {
+#ifdef TIMING
+    Timer t("OSDTypeText::DrawString");
+#endif
+
     if (m_centered || m_right)
     {
         int textlength = 0;
@@ -713,6 +764,8 @@
     m_isvalid = false;
     m_imagesize = QRect(0, 0, 0, 0);
 
+    m_i44 = NULL;
+
     m_scalew = scalew;
     m_scaleh = scaleh;
 
@@ -734,6 +787,8 @@
     m_scaleh = other.m_scaleh;
 
     m_alpha = m_yuv = NULL;
+    m_i44 = NULL;
+
     if (m_isvalid)
     {
         int size = m_imagesize.width() * m_imagesize.height() * 3 / 2;
@@ -749,7 +804,11 @@
         m_ubuffer = m_yuv + (m_imagesize.width() * m_imagesize.height());
         m_vbuffer = m_yuv + (m_imagesize.width() * m_imagesize.height() * 
                              5 / 4);
-    } 
+
+//I44
+        m_i44 = new unsigned char[size];
+        memcpy(m_i44, other.m_i44, size);
+    }
 }
 
 OSDTypeImage::OSDTypeImage(const QString &name)
@@ -767,6 +826,8 @@
     m_vbuffer = NULL;
     m_isvalid = false;
     m_filename = "";
+
+    m_i44 = NULL;
 }
 
 OSDTypeImage::OSDTypeImage(void)
@@ -785,6 +846,8 @@
     m_vbuffer = NULL;
     m_isvalid = false;
     m_filename = "";
+
+    m_i44 = NULL;
 }
 
 OSDTypeImage::~OSDTypeImage()
@@ -793,6 +856,8 @@
         delete [] m_yuv;
     if (m_alpha)
         delete [] m_alpha;
+    if (m_i44)
+        delete [] m_i44;
 }
 
 void OSDTypeImage::SetName(const QString &name)
@@ -811,7 +876,58 @@
     LoadImage(m_filename, wmult, hmult, m_scalew, m_scaleh);
 }
 
-void OSDTypeImage::LoadImage(const QString &filename, float wmult, float hmult,
+void rgb32_to_i44(unsigned char*i44, unsigned char*rgb, int width, int height, int srcwidth, const QValueList<QColor> &palette )
+{
+    int wrap, wrap4, x, y;
+    unsigned char *p;
+    unsigned char ch, r, g, b;
+
+printf("rgb32_to_i44 called, image size: %dx%d\n", width, height);
+
+    p = rgb;
+
+    for (y=0; y<height; y++)
+    {
+        unsigned char *pstart=p;
+
+        for (x=0; x<width; x++)
+        {
+            ch = (p[3] >> 4) & 0x0f; //trunc alpha
+            r=p[2]; g=p[1]; b=p[0];
+
+            //Find nearest palette colour
+            long d1, d2=( 256*256 )*3; //black is white
+            int i, j;
+            for ( i=0;i<palette.count(); i++ )
+            {
+                d1 = ( palette[i].red()-r ) * ( palette[i].red()-r ) +
+                     ( palette[i].green()-g ) * ( palette[i].green()-g ) +
+                     ( palette[i].blue()-b ) * ( palette[i].blue()-b );
+
+                if ( d1==0 ) { //perfect match
+                    j=i;
+                    break;
+                }
+                if ( d1 < d2 ) { //nearer match
+                    d2 = d1;
+                    j=i;
+                }
+            }
+
+            ch |= ( j<<4 );
+
+            *(i44+x+y*width) = ch;
+
+            p+=4;
+        }
+
+        p=pstart+srcwidth*4;
+
+    }
+}
+
+void OSDTypeImage::LoadImage(const QString &filename, 
+                             float wmult, float hmult, 
                              int scalew, int scaleh)
 {
     if (m_isvalid)
@@ -820,10 +936,13 @@
             delete [] m_yuv;
         if (m_alpha)
             delete [] m_alpha;
+        if (m_i44)
+            delete [] m_i44;
 
         m_isvalid = false;
         m_yuv = NULL;
         m_alpha = NULL;
+        m_i44 = NULL;
     }
 
     if (filename.length() < 2)
@@ -862,9 +981,14 @@
 
     m_alpha = new unsigned char[imwidth * imheight];
 
-    rgb32_to_yuv420p(m_ybuffer, m_ubuffer, m_vbuffer, m_alpha, tmp2.bits(),
+    m_i44 = new unsigned char[imwidth*imheight];
+
+    rgb32_to_yuv420p(m_ybuffer, m_ubuffer, m_vbuffer, m_alpha, tmp2.bits(), 
                      imwidth, imheight, tmp2.width());
 
+    rgb32_to_i44(m_i44, tmp2.bits(), imwidth, imheight, tmp2.width(),
+                 GetPalette());
+
     m_imagesize = QRect(0, 0, imwidth, imheight);
 }
 
@@ -877,9 +1001,13 @@
         if (m_alpha)
             delete [] m_alpha;
 
+        if (m_i44)
+            delete[] m_i44;
+
         m_isvalid = false;
         m_yuv = NULL;
         m_alpha = NULL;
+        m_i44 = NULL;
     }
 
     m_isvalid = true;
@@ -894,18 +1022,144 @@
 
     m_alpha = new unsigned char[imwidth * imheight];
 
-    rgb32_to_yuv420p(m_ybuffer, m_ubuffer, m_vbuffer, m_alpha, img.bits(),
+    m_i44 = new unsigned char[imwidth*imheight];
+
+    rgb32_to_yuv420p(m_ybuffer, m_ubuffer, m_vbuffer, m_alpha, img.bits(), 
                      img.width(), img.height(), img.bytesPerLine() / 4);
 
+    rgb32_to_i44(m_i44, img.bits(), imwidth, imheight, img.width(),
+                 GetPalette());
     m_imagesize = QRect(0, 0, imwidth, imheight);
 }
 
-void OSDTypeImage::Draw(OSDSurface *surface, int fade, int maxfade,
-                        int xoff, int yoff)
+void OSDTypeImage::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff)
 {
+#ifdef TIMING
+Timer t("OSDTypeImage::Draw");
+#endif
+
+    if (surface->SurfaceType()==OSDSurface::SURF_YUV)
+        Draw((YUVSurface*)surface, fade, maxfade, xoff, yoff);
+    else if (surface->SurfaceType()==OSDSurface::SURF_I44)
+        Draw((I44Surface*)surface, fade, maxfade, xoff, yoff);
+}
+
+void OSDTypeImage::Draw(I44Surface *surface, int fade, int maxfade, int xoff, 
+                        int yoff)
+{
     if (!m_isvalid)
         return;
 
+    unsigned char *dest, *destalpha, *src, *srcalpha;
+    unsigned char *udest, *vdest, *usrc, *vsrc;
+    int alpha, iwidth, width;
+
+    iwidth = width = m_imagesize.width();
+    int height = m_imagesize.height();
+
+    if (m_drawwidth >= 0)
+        width = m_drawwidth;
+
+    int ystart = m_displaypos.y();
+    int xstart = m_displaypos.x();
+
+    xstart += xoff;
+    ystart += yoff;
+
+    ystart = (ystart / 2) * 2;
+    xstart = ((xstart + 1) / 2) * 2;
+
+    int startline = 0;
+    int startcol = 0;
+
+    if (ystart < 0)
+    {
+        startline = 0 - ystart;
+        ystart = 0;
+    }
+
+    if (xstart < 0)
+    {
+        startcol = 0 - xstart;
+        xstart = 0;
+    }
+
+    if (height + ystart > surface->height)
+        height = surface->height - ystart - 1;
+    if (width + xstart > surface->width)
+        width = surface->width - xstart - 1;
+
+    if (width == 0 || height == 0)
+{
+printf("zeros\n");
+        return;
+}
+
+
+    QRect destRect = QRect(xstart, ystart, width, height);
+    bool needblend = false;
+
+    if (m_onlyusefirst || surface->IntersectsDrawn(destRect))
+        needblend = true;
+    surface->AddRect(destRect);
+
+    int ysrcwidth;
+    int ydestwidth;
+
+    int uvsrcwidth;
+    int uvdestwidth;
+
+    int alphamod = 0xf;
+
+
+    if (maxfade > 0 && fade >= 0)
+        alphamod = (int)((((float)(fade) / maxfade) * 16.0) + 0.5);
+
+unsigned char almap[256];
+    {
+for (int i=0; i<256; i++)
+{
+almap[i] = ( i & 0xf0)|((((i & 0xf) * alphamod)>>4)&0xf);
+}
+}
+        unsigned char *dst;
+
+        src = m_i44;
+        dst = surface->i44buffer + xstart + (ystart)*surface->width;
+
+        unsigned long *ldst = (unsigned long*)dst;
+
+{
+        for (int y = startline; y < height; y++)
+        {
+            unsigned long *lsrc = (unsigned long*)(src+(y*iwidth));
+            for (int x = startcol/4; x < width/4; x++)
+            {
+                unsigned long sch = lsrc[x];
+                unsigned long dsh =
+                            almap[sch>>24]<<24 |
+                            almap[sch>>16 & 0xff] << 16 |
+                            almap[sch>>8 & 0xff] << 8 |
+                            almap[sch&0xff];
+
+                ldst[x] = (ldst[x] & 0x0f0f0f0f) | dsh;
+
+/* unsigned char ch = (alphamod & 0xf0) | (*(m_ubuffer+(x/2)+ysrcwidth) & 0x0f) ;
+                *(surface->i44buffer + x +xstart+ ydestwidth) = ch;
+*/
+            }
+            ldst+=surface->width/4;
+        }
+}
+        return;
+
+}
+void OSDTypeImage::Draw(YUVSurface *surface, int fade, int maxfade, int xoff, 
+                        int yoff)
+{
+    if (!m_isvalid)
+        return;
+
     int xstart = ((m_displaypos.x() + xoff + 1) / 2) * 2;
     int ystart = ((m_displaypos.y() + yoff)     / 2) * 2;
 
@@ -933,7 +1187,7 @@
 
     drawheight = (drawheight + ystart > surface->height) ?
         surface->height - ystart - 1 : drawheight;
- 
+
     if ((drawwidth <= 0) || (drawheight <= 0))
         return;
 
@@ -941,7 +1195,7 @@
     bool needblend = m_onlyusefirst || surface->IntersectsDrawn(destRect);
 
     surface->AddRect(destRect);
-    
+
     int alphamod = 255;
 
     if (maxfade > 0 && fade >= 0)
@@ -954,7 +1208,7 @@
             int ysrcwidth = y * iwidth;
             int ydestwidth = (y + ystart - startline) * surface->width;
 
-            memcpy(surface->y + xstart + ydestwidth,
+            memcpy(surface->y + xstart + ydestwidth, 
                    m_ybuffer + startcol + ysrcwidth, drawwidth);
 
             unsigned char *destalpha = surface->alpha + xstart + ydestwidth;
@@ -962,7 +1216,7 @@
             for (int x = startcol; x < drawwidth; x++)
             {
                 int alpha = *(m_alpha + x + ysrcwidth);
-  
+
                 if (alpha == 0)
                     *destalpha = 0;
                 else
@@ -985,9 +1239,9 @@
             int uvsrcwidth = y * iwidth;
             int uvdestwidth = (y + ystart - startline) * (surface->width / 2);
 
-            memcpy(surface->u + xstart + uvdestwidth,
+            memcpy(surface->u + xstart + uvdestwidth, 
                    m_ubuffer + startcol + uvsrcwidth, drawwidth);
-            memcpy(surface->v + xstart + uvdestwidth,
+            memcpy(surface->v + xstart + uvdestwidth, 
                    m_vbuffer + startcol + uvsrcwidth, drawwidth);
         }
 
@@ -1012,28 +1266,28 @@
     unsigned char *destalpha = surface->alpha + xstart     + ydestwidth;
 
     if (m_onlyusefirst)
-        (surface->blendcolumnfunc) (src, usrc, vsrc, srcalpha, iwidth, dest,
-                                    udest, vdest, destalpha, surface->width,
+        (surface->blendcolumnfunc) (src, usrc, vsrc, srcalpha, iwidth, dest, 
+                                    udest, vdest, destalpha, surface->width, 
                                     drawwidth - startcol, 
-                                    drawheight - startline,
-                                    alphamod, 1, surface->rec_lut,
+                                    drawheight - startline, 
+                                    alphamod, 1, surface->rec_lut, 
                                     surface->pow_lut);
     else
-        (surface->blendregionfunc) (src, usrc, vsrc, srcalpha, iwidth, dest,
-                                    udest, vdest, destalpha, surface->width,
+        (surface->blendregionfunc) (src, usrc, vsrc, srcalpha, iwidth, dest, 
+                                    udest, vdest, destalpha, surface->width, 
                                     drawwidth - startcol, 
-                                    drawheight - startline,
-                                    alphamod, 1, surface->rec_lut,
+                                    drawheight - startline, 
+                                    alphamod, 1, surface->rec_lut, 
                                     surface->pow_lut);
 }
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-OSDTypePosSlider::OSDTypePosSlider(const QString &name,
-                                   const QString &filename,
-                                   QRect displayrect, float wmult,
+OSDTypePosSlider::OSDTypePosSlider(const QString &name, 
+                                   const QString &filename, 
+                                   QRect displayrect, float wmult, 
                                    float hmult, int scalew, int scaleh)
-               : OSDTypeImage(name, filename, displayrect.topLeft(), wmult,
+               : OSDTypeImage(name, filename, displayrect.topLeft(), wmult, 
                               hmult, scalew, scaleh)
 {
     m_maxval = 1000;
@@ -1045,7 +1299,7 @@
 {
 }
 
-void OSDTypePosSlider::Reinit(float wchange, float hchange, float wmult,
+void OSDTypePosSlider::Reinit(float wchange, float hchange, float wmult, 
                               float hmult)
 {
     int width = (int)(m_displayrect.width() * wchange);
@@ -1077,7 +1331,7 @@
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 OSDTypeFillSlider::OSDTypeFillSlider(const QString &name, 
-                                     const QString &filename,
+                                     const QString &filename, 
                                      QRect displayrect, float wmult, 
                                      float hmult, int scalew, int scaleh)
                  : OSDTypeImage(name, filename, displayrect.topLeft(), wmult, 
@@ -1094,7 +1348,7 @@
 {
 }
 
-void OSDTypeFillSlider::Reinit(float wchange, float hchange, float wmult,
+void OSDTypeFillSlider::Reinit(float wchange, float hchange, float wmult, 
                                float hmult)
 {
     int width = (int)(m_displayrect.width() * wchange);
@@ -1129,10 +1383,10 @@
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-OSDTypeEditSlider::OSDTypeEditSlider(const QString &name,
-                                     const QString &bluefilename,
-                                     const QString &redfilename,
-                                     QRect displayrect, float wmult,
+OSDTypeEditSlider::OSDTypeEditSlider(const QString &name, 
+                                     const QString &bluefilename, 
+                                     const QString &redfilename, 
+                                     QRect displayrect, float wmult, 
                                      float hmult, int scalew, int scaleh)
                  : OSDTypeImage(name)
 {
@@ -1146,7 +1400,7 @@
          m_drawMap[i] = 0;
 
     m_displaypos = displayrect.topLeft();
-    
+
     m_yuv = m_alpha = NULL;
     m_isvalid = false;
 
@@ -1187,7 +1441,7 @@
         delete [] m_ralpha;
 }
 
-void OSDTypeEditSlider::Reinit(float wchange, float hchange, float wmult,
+void OSDTypeEditSlider::Reinit(float wchange, float hchange, float wmult, 
                                float hmult)
 {
     int width = (int)(m_displayrect.width() * wchange);
@@ -1199,7 +1453,7 @@
     m_drawwidth = m_displayrect.width();
 
     delete [] m_drawMap;
-    
+
     m_drawMap = new unsigned char[m_drawwidth + 1];
     for (int i = 0; i < m_drawwidth; i++)
          m_drawMap[i] = 0;
@@ -1242,7 +1496,7 @@
 
     if (start < 0)
         start = 0;
-    if (start >= m_drawwidth) 
+    if (start >= m_drawwidth)
         start = m_drawwidth - 1;
     if (end < 0)
         end = 0;
@@ -1260,15 +1514,23 @@
         m_drawMap[i] = 1;
 }
 
-void OSDTypeEditSlider::Draw(OSDSurface *surface, int fade, int maxfade,
+void OSDTypeEditSlider::Draw(OSDSurface *surface, int fade, int maxfade, 
                              int xoff, int yoff)
-{           
+{
+    if (surface->SurfaceType()==OSDSurface::SURF_YUV)
+        Draw((YUVSurface*)surface, fade, maxfade, xoff, yoff);
+//    else if (surface->SurfaceType()==OSDSurface::SURF_I44)
+//        Draw((I44Surface*)surface, fade, maxfade, xoff, yoff);
+}
+void OSDTypeEditSlider::Draw(YUVSurface *surface, int fade, int maxfade, 
+                             int xoff, int yoff)
+{
     if (!m_isvalid || !m_risvalid)
         return;
-            
+
     unsigned char *dest, *destalpha, *src, *rsrc, *srcalpha, *rsrcalpha;
     unsigned char *udest, *vdest, *usrc, *rusrc, *vsrc, *rvsrc;
-            
+
     int iwidth, riwidth, width;
     iwidth = m_imagesize.width();
     riwidth = m_rimagesize.width();
@@ -1277,7 +1539,7 @@
 
     int ystart = m_displaypos.y();
     int xstart = m_displaypos.x();
-            
+
     xstart += xoff;
     ystart += yoff;
 
@@ -1309,21 +1571,21 @@
 
     QRect destRect = QRect(xstart, ystart, width, height);
     surface->AddRect(destRect);
- 
-    int ysrcwidth;              
+
+    int ysrcwidth;
     int rysrcwidth;
     int ydestwidth;
-   
+
     int uvsrcwidth;
     int ruvsrcwidth;
     int uvdestwidth;
- 
+
     int alphamod = 255;
-    
+
     if (maxfade > 0 && fade >= 0)
         alphamod = (int)((((float)(fade) / maxfade) * 256.0) + 0.5);
 
-    ysrcwidth = startline * iwidth; 
+    ysrcwidth = startline * iwidth;
     rysrcwidth = startline * riwidth;
     ydestwidth = ystart * surface->width;
 
@@ -1346,17 +1608,17 @@
     vdest = surface->v + xstart / 2 + uvdestwidth;
     vsrc = m_vbuffer + uvsrcwidth;
     rvsrc = m_rvbuffer + ruvsrcwidth;
-    (surface->blendcolumn2func) (rsrc, rusrc, rvsrc, rsrcalpha, riwidth, src,
-                                 usrc, vsrc, srcalpha, iwidth,
-                                 m_drawMap + startcol, dest, udest, vdest,
-                                 destalpha, surface->width, width - startcol,
-                                 height - startline, alphamod, 1,
+    (surface->blendcolumn2func) (rsrc, rusrc, rvsrc, rsrcalpha, riwidth, src, 
+                                 usrc, vsrc, srcalpha, iwidth, 
+                                 m_drawMap + startcol, dest, udest, vdest, 
+                                 destalpha, surface->width, width - startcol, 
+                                 height - startline, alphamod, 1, 
                                  surface->rec_lut, surface->pow_lut);
 }
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-OSDTypeBox::OSDTypeBox(const QString &name, QRect displayrect) 
+OSDTypeBox::OSDTypeBox(const QString &name, QRect displayrect)
           : OSDType(name)
 {
     size = displayrect;
@@ -1385,8 +1647,22 @@
 void OSDTypeBox::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, 
                       int yoff)
 {
+#ifdef TIMING
+Timer t("OSDTypeBox::Draw");
+#endif
+
+    if (surface->SurfaceType()==OSDSurface::SURF_YUV)
+        Draw((YUVSurface*)surface, fade, maxfade, xoff, yoff);
+    else if (surface->SurfaceType()==OSDSurface::SURF_I44)
+        Draw((I44Surface*)surface, fade, maxfade, xoff, yoff);
+}
+
+void OSDTypeBox::Draw(I44Surface *surface, int fade, int maxfade, int xoff, 
+                      int yoff)
+{
     unsigned char *dest, *destalpha;
     unsigned char alpha = 192;
+    unsigned char targ;
 
     QRect disprect = size;
     disprect.moveBy(xoff, yoff);
@@ -1407,6 +1683,56 @@
 
     int height = yend - ystart + 1, width = xend - xstart + 1;
 
+    QRect destRect = QRect(xstart, ystart, width, height);
+    bool needblend = false;
+
+    if (surface->IntersectsDrawn(destRect))
+        needblend = true;
+    surface->AddRect(destRect);
+
+    int alphamod = 255;
+    if (maxfade > 0 && fade >= 0)
+        alphamod = (int)((((float)(fade) / maxfade) * 16.0) + 0.5);
+
+    int ydestwidth;
+
+    alpha = ((alpha * alphamod) + 0x8);
+
+    targ = 0 | (alpha & 0xf); //black
+//targ=0xf3;
+
+    for (int y = ystart; y < yend; y++)
+    {
+        ydestwidth = y * surface->width;
+        memset(surface->i44buffer + xstart + ydestwidth, targ , width);
+    }
+}
+
+void OSDTypeBox::Draw(YUVSurface *surface, int fade, int maxfade, int xoff, 
+                      int yoff)
+{
+    unsigned char *dest, *destalpha;
+    unsigned char alpha = 192;
+
+    QRect disprect = size;
+    disprect.moveBy(xoff, yoff);
+
+    int ystart = disprect.top();
+    int yend = disprect.bottom();
+    int xstart = disprect.left();
+    int xend = disprect.right();
+
+    if (xstart < 0)
+        xstart = 0;
+    if (xend > surface->width)
+        xend = surface->width;
+    if (ystart < 0)
+        ystart = 0;
+    if (yend > surface->height)
+        yend = surface->height;
+
+    int height = yend - ystart + 1, width = xend - xstart + 1;
+
     QRect destRect = QRect(xstart, ystart, width, height); 
     bool needblend = false;
 
@@ -1533,6 +1859,19 @@
 void OSDTypePositionRectangle::Draw(OSDSurface *surface, int fade, int maxfade, 
                                     int xoff, int yoff)
 {
+#ifdef TIMING
+Timer t("OSDTypePositionRectangle::Draw");
+#endif
+
+    if (surface->SurfaceType()==OSDSurface::SURF_YUV)
+        Draw((YUVSurface*)surface, fade, maxfade, xoff, yoff);
+    else if (surface->SurfaceType()==OSDSurface::SURF_I44)
+        Draw((I44Surface*)surface, fade, maxfade, xoff, yoff);
+}
+
+void OSDTypePositionRectangle::Draw(YUVSurface *surface, int fade, int maxfade, 
+                                    int xoff, int yoff)
+{
     fade = fade;
     maxfade = maxfade;
     xoff = xoff;
@@ -1611,6 +1950,80 @@
     }
 }
 
+
+void OSDTypePositionRectangle::Draw(I44Surface *surface, int fade, int maxfade, 
+                                    int xoff, int yoff)
+{
+    fade = fade;
+    maxfade = maxfade;
+    xoff = xoff;
+    yoff = yoff;
+
+    if (m_curposition < 0 || m_curposition >= m_numpositions)
+        return;
+
+    QRect rect = positions[m_curposition];
+
+    unsigned char *src;
+    int ystart = rect.top();
+    int yend = rect.bottom();
+    int xstart = rect.left();
+    int xend = rect.right();
+
+    int height = yend - ystart + 1, width = xend - xstart + 1;
+
+    QRect destRect = QRect(xstart, ystart, width, height);
+    surface->AddRect(destRect);
+
+
+    for (int y = ystart; y < yend; y++)
+    {
+        if (y < 0 || y >= surface->height)
+            continue;
+
+        for (int x = xstart; x < xstart + 2; x++)
+        {
+            if (x < 0 || x >= surface->width)
+                continue;
+
+            src = surface->i44buffer + x + y * surface->width;
+            *src = 0xaa; //white
+        }
+
+        for (int x = xend - 2; x < xend; x++)
+        {
+            if (x < 0 || x >= surface->width)
+                continue;
+
+            src = surface->i44buffer + x + y * surface->width;
+            *src = 0xaa; //white
+        }
+    }
+
+    for (int x = xstart; x < xend; x++)
+    {
+        if (x < 0 || x >= surface->width)
+            continue;
+
+        for (int y = ystart; y < ystart + 2; y++)
+        {
+            if (y < 0 || y >= surface->height)
+                continue;
+
+            src = surface->i44buffer + x + y * surface->width;
+            *src = 0xaa;
+        }
+        for (int y = yend - 2; y < yend; y++)
+        {
+            if (y < 0 || y >= surface->height)
+                continue;
+
+            src = surface->i44buffer + x + y * surface->width;
+            *src = 0xaa;
+        }
+    }
+}
+
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 OSDTypePositionImage::OSDTypePositionImage(const QString &name)
Index: libs/libmythtv/videooutbase.cpp
===================================================================
--- libs/libmythtv/videooutbase.cpp	(revision 7663)
+++ libs/libmythtv/videooutbase.cpp	(working copy)
@@ -1172,13 +1172,17 @@
     if (!osd)
         return -1;
 
-    OSDSurface *surface = osd->Display();
-    if (!surface)
+    OSDSurface *osdsurf = osd->Display();
+    if (!osdsurf)
         return -1;
 
     bool changed = (-1 == revision) ?
-        surface->Changed() : (surface->GetRevision()!=revision);
+        osdsurf->Changed() : (osdsurf->GetRevision()!=revision);
 
+    if (osdsurf->SurfaceType() == OSDSurface::SURF_YUV)
+    {
+        YUVSurface *surface = (YUVSurface*)osdsurf;
+
     switch (frame->codec)
     {
         case FMT_YV12:
@@ -1213,6 +1217,15 @@
         default:
             break;
     }
+    }
+    else if (osdsurf->SurfaceType() == OSDSurface::SURF_I44)
+    {
+        I44Surface* surface=(I44Surface*)osdsurf;
+
+        if (changed)
+            surface->BlendToI44( frame->buf, false, stride, XJ_height);
+    }
+
     return (changed) ? 1 : 0;
 }
 
Index: libs/libmythtv/osdtypes.h
===================================================================
--- libs/libmythtv/osdtypes.h	(revision 7651)
+++ libs/libmythtv/osdtypes.h	(working copy)
@@ -14,8 +14,12 @@
 class TTFFont;
 class OSDType;
 class OSDSurface;
+class YUVSurface;
+class I44Surface;
 class TV;
 
+struct Raster_Map;
+
 class OSDSet : public QObject
 {
     Q_OBJECT
@@ -214,6 +218,8 @@
     bool m_scrollinit;
 
     float m_linespacing;
+
+    Raster_Map *m_raster;
 };
     
 class OSDTypeImage : public OSDType
@@ -247,7 +253,18 @@
 
     virtual void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, 
                       int yoff);
+    void Draw(YUVSurface *surface, int fade, int maxfade, int xoff, 
+                      int yoff);
+    void Draw(I44Surface *surface, int fade, int maxfade, int xoff, 
+              int yoff);
 
+// TODO this should not be static -- dtk
+    static void SetPalette(const QValueList<QColor> &palette)
+        { s_palette = palette; }
+// TODO this should not be static -- dtk
+// TODO QValueList here is unsafe, QValueList is not threadsafe -- dtk
+    static QValueList<QColor> GetPalette(void) { return s_palette; }
+
   protected:
     QRect m_imagesize;
     QPoint m_displaypos;
@@ -263,10 +280,18 @@
 
     unsigned char *m_alpha;
 
+    unsigned char *m_i44;
+
     int m_scalew, m_scaleh;
+    float m_wmult, m_hmult;
 
     int m_drawwidth;
     bool m_onlyusefirst;
+
+// Cant think of a clean way to get this to all the osdtypes that need it.
+// TODO this should not be static -- dtk
+// TODO QValueList is not threadsafe -- dtk
+    static QValueList<QColor> s_palette;
 };
 
 class OSDTypePosSlider : public OSDTypeImage
@@ -333,6 +358,8 @@
     void SetRange(int start, int end);
 
     void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
+    void Draw(YUVSurface *surface, int fade, int maxfade, int xoff, int yoff);
+    void Draw(I44Surface *surface, int fade, int maxfade, int xoff, int yoff);
 
   private:
     QRect m_displayrect;
@@ -365,6 +392,8 @@
     void SetRect(QRect newrect) { size = newrect; }
 
     void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
+    void Draw(YUVSurface *surface, int fade, int maxfade, int xoff, int yoff);
+    void Draw(I44Surface *surface, int fade, int maxfade, int xoff, int yoff);
 
   private:
     QRect size;
@@ -405,6 +434,8 @@
     void Reinit(float wchange, float hchange);
 
     void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
+    void Draw(YUVSurface *surface, int fade, int maxfade, int xoff, int yoff);
+    void Draw(I44Surface *surface, int fade, int maxfade, int xoff, int yoff);
 
   private:
     vector<QRect> positions; 
Index: libs/libmythtv/videoout_xv.cpp
===================================================================
--- libs/libmythtv/videoout_xv.cpp	(revision 7663)
+++ libs/libmythtv/videoout_xv.cpp	(working copy)
@@ -2622,6 +2622,12 @@
     XvMCOSD* xvmc_osd = GetAvailableOSD();
     if (osd && xvmc_osd->IsValid())
     {
+        if (osd->HasPalette() && !xvmc_osd->CustomPalette())
+        {
+            VERBOSE(VB_PLAYBACK, LOC + "Setting XvMC OSD palette");
+            xvmc_osd->SetPalette(osd->GetPalette());
+        }
+
         VideoFrame *osdframe = NULL;
         int ret = DisplayOSD(xvmc_osd->OSDFrame(), osd, -1,
                              xvmc_osd->GetRevision());
@@ -3359,9 +3365,13 @@
     Reinit(next);
 
     // then blend the OSD onto it
-    unsigned char *buf = (unsigned char*) shm_infos[next].shmaddr;
-    osdsurf->BlendToARGB(buf, img[next]->bytes_per_line, vf[next].height,
-                         false/*blend_to_black*/, 16);
+    YUVSurface *yuvsurf = dynamic_cast<YUVSurface*>(osdsurf);
+    if (yuvsurf)
+    {
+        unsigned char *buf = (unsigned char*) shm_infos[next].shmaddr;
+        yuvsurf->BlendToARGB(buf, img[next]->bytes_per_line, vf[next].height,
+                             false/*blend_to_black*/, 16);
+    }
 
     // then set it as the current OSD image
     revision = osdsurf->GetRevision();
Index: libs/libmythtv/osdxvmc.h
===================================================================
--- libs/libmythtv/osdxvmc.h	(revision 7651)
+++ libs/libmythtv/osdxvmc.h	(working copy)
@@ -28,6 +28,9 @@
     void DeleteBuffer();
     void CompositeOSD(VideoFrame* frame, VideoFrame* osdframe=NULL);
 
+    void SetPalette( const QValueList<QColor> &palette );
+    bool CustomPalette() { return custompalette; }
+
     VideoFrame *OSDFrame()
     {
         tmpframe.codec =
@@ -55,6 +58,7 @@
     int                  osd_subpict_clear_color;
     bool                 osd_subpict_alloc;
 
+    bool                 custompalette;
     VideoFrame           tmpframe;
     int                  revision;
 };
Index: libs/libmythtv/osdxvmc.cpp
===================================================================
--- libs/libmythtv/osdxvmc.cpp	(revision 7651)
+++ libs/libmythtv/osdxvmc.cpp	(working copy)
@@ -25,7 +25,8 @@
     : XJ_disp(disp), XJ_width(0), XJ_height(0),
       xv_port(port), osd_palette(NULL), osd_xv_image(NULL),
       osd_subpict_mode(NO_SUBPICTURE), osd_subpict_clear_color(0),
-      osd_subpict_alloc(false)
+      osd_subpict_alloc(false),
+      custompalette(false)
 {
     // subpicture init
     int num = 0;
@@ -131,6 +132,46 @@
     osd_subpict_alloc = true;
 }
 
+void XvMCOSD::SetPalette(const QValueList<QColor> &palette)
+{
+    int i;
+    custompalette = true;
+    int entries = palette.count();
+
+    VERBOSE(VB_PLAYBACK, QString("SetPalette entries %1").arg(entries));
+
+    if (entries > osd_subpict.num_palette_entries)
+        entries = osd_subpict.num_palette_entries;
+    int seb = osd_subpict.entry_bytes;
+
+    for (i=0; i<entries; i++)
+    {
+        int r = palette[i].red();
+        int g = palette[i].green();
+        int b = palette[i].blue();
+        
+        int Y = (int)((0.257*r)+(0.504*g)+(0.098*b)+16);
+        int U = (int)(-(0.148*r)-(0.291*g)+(0.439*b)+128);
+        int V = (int)((0.439*r)-(0.368*g)-(0.071*b)+128);
+                        
+        VERBOSE(VB_PLAYBACK,
+                QString("Colour: Y=%1 U=%1 V=%1" ).arg(Y).arg(U).arg(V));
+
+        for (int j = 0; j < seb; j++)
+        {
+            switch (osd_subpict.component_order[j]) 
+            {
+                case 'U': osd_palette[i * seb + j] = U; break;
+                case 'V': osd_palette[i * seb + j] = V; break;
+                case 'Y':
+                    default:  osd_palette[i * seb + j] = Y; break;
+            }
+        }
+    }
+    
+    X11S(XvMCSetSubpicturePalette(XJ_disp, &osd_subpict, osd_palette));
+}
+
 void XvMCOSD::DeleteBuffer()
 {
     if (!osd_subpict_alloc)
Index: libs/libmythtv/osdsurface.cpp
===================================================================
--- libs/libmythtv/osdsurface.cpp	(revision 7651)
+++ libs/libmythtv/osdsurface.cpp	(working copy)
@@ -11,19 +11,53 @@
 
 #endif
 
-OSDSurface::OSDSurface(int w, int h)
+OSDSurface::OSDSurface(int w, int h) :
+    width(std::max(w,0)), height(std::max(h,0)), size(width * height)
 {
+    Clear();
+}
+
+OSDSurface::~OSDSurface()
+{
+}
+
+void OSDSurface::Clear(void)
+{
+    usedRegions = QRegion();
+}
+
+void OSDSurface::ClearUsed(void)
+{
+}
+
+bool OSDSurface::IntersectsDrawn(QRect &newrect)
+{
+    QMemArray<QRect> rects = usedRegions.rects();
+    QMemArray<QRect>::Iterator it = rects.begin();
+
+    for (; it != rects.end(); ++it)
+    {
+        if (newrect.intersects(*it))
+            return true;
+    }
+
+    return false;
+}
+
+void OSDSurface::AddRect(QRect &newrect)
+{
+    usedRegions = usedRegions.unite(newrect);
+}
+
+YUVSurface::YUVSurface(int w, int h) :
+    OSDSurface(w, h)
+{
     yuvbuffer = new unsigned char[w * (h + 2) * 3 / 2];
     y = yuvbuffer;
     u = yuvbuffer + w * h;
     v = u + w * h / 4;
     alpha = new unsigned char[w * (h + 2)];
 
-    width = w;
-    height = h;
-
-    size = width * height;
-
     for (int i = 0; i < 256; i++)
     {
         for (int j = 0; j < 256; j++)
@@ -72,22 +106,23 @@
     revision = 0;
 }
 
-OSDSurface::~OSDSurface()
+YUVSurface::~YUVSurface()
 {
     delete [] yuvbuffer;
     delete [] alpha;
 }
 
-void OSDSurface::Clear(void)
+void YUVSurface::Clear(void)
 {
     memset(y, 0, size);
     memset(u, 127, size / 4);
     memset(v, 127, size / 4);
     memset(alpha, 0, size);
-    usedRegions = QRegion();
+    
+    OSDSurface::Clear();
 }
 
-void OSDSurface::ClearUsed(void)
+void YUVSurface::ClearUsed(void)
 {
     QMemArray<QRect> rects = usedRegions.rects();
     QMemArray<QRect>::Iterator it = rects.begin();
@@ -127,23 +162,11 @@
     }
 
     usedRegions = QRegion();
+    
+    OSDSurface::Clear();
 }
 
-bool OSDSurface::IntersectsDrawn(QRect &newrect)
-{
-    QMemArray<QRect> rects = usedRegions.rects();
-    QMemArray<QRect>::Iterator it = rects.begin();
-    for (; it != rects.end(); ++it)
-        if (newrect.intersects(*it))
-            return true;
-    return false;
-}
 
-void OSDSurface::AddRect(QRect &newrect)
-{
-    usedRegions = usedRegions.unite(newrect);
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Helper functions
 ///////////////////////////////////////////////////////////////////////////
@@ -251,7 +274,7 @@
 }
 #endif
 
-blendtoyv12_8_fun blendtoyv12_8_init(const OSDSurface *surface)
+blendtoyv12_8_fun blendtoyv12_8_init(const YUVSurface *surface)
 {
     (void)surface;
 #ifdef MMX
@@ -261,7 +284,7 @@
     return blendalpha8_c;
 }
 
-static inline void blendtoargb_8_c(const OSDSurface *surf, unsigned char *src,
+static inline void blendtoargb_8_c(const YUVSurface *surf, unsigned char *src,
                                    unsigned char *usrc, unsigned char *vsrc,
                                    unsigned char *alpha, unsigned char *dest)
 {
@@ -283,7 +306,8 @@
 
 #ifdef MMX
 #define movntq(src, dest) movq_r2m(src, dest);
-static inline void blendtoargb_8_mmx(const OSDSurface * /*surf*/, unsigned char *src,
+static inline void blendtoargb_8_mmx(const YUVSurface * /*surf*/,
+                                     unsigned char *src,
                                      unsigned char *usrc, unsigned char *vsrc,
                                      unsigned char *alpha, unsigned char *dest)
 {
@@ -378,7 +402,7 @@
 }
 #endif
 
-blendtoargb_8_fun blendtoargb_8_init(const OSDSurface *surface)
+blendtoargb_8_fun blendtoargb_8_init(const YUVSurface *surface)
 {
     (void)surface;
 #ifdef MMX
@@ -494,7 +518,7 @@
 }
 #endif
 
-dithertoia44_8_fun dithertoia44_8_init(const OSDSurface* /*surface*/)
+dithertoia44_8_fun dithertoia44_8_init(const YUVSurface* /*surface*/)
 {
 #ifdef MMX
 // mmx version seems to be about the same speed, no reason to use it.
@@ -543,13 +567,13 @@
     delete context;
 }
 
-/** \fn OSDSurface::BlendToYV12(unsigned char *) const
- *  \brief Alpha blends OSDSurface to yuv buffer of the same size.
+/** \fn YUVSurface::BlendToYV12(unsigned char *) const
+ *  \brief Alpha blends YUVSurface to yuv buffer of the same size.
  *  \param yuvptr Pointer to YUV buffer to blend OSD to.
  */
-void OSDSurface::BlendToYV12(unsigned char *yuvptr) const
+void YUVSurface::BlendToYV12(unsigned char *yuvptr) const
 {
-    const OSDSurface *surface = this;
+    const YUVSurface *surface = this;
     blendtoyv12_8_fun blender = blendtoyv12_8_init(surface);
 
     unsigned char *uptrdest = yuvptr + surface->width * surface->height;
@@ -668,8 +692,8 @@
     }
 }
 
-/** \fn OSDSurface::BlendToARGB(unsigned char *,uint,uint,bool) const
- *  \brief Alpha blends OSDSurface to ARGB buffer.
+/** \fn YUVSurface::BlendToARGB(unsigned char *,uint,uint,bool) const
+ *  \brief Alpha blends YUVSurface to ARGB buffer.
  *
  *  \todo Currently blend_to_black is implemented as a post process
  *        on the whole frame, it would make sense to make this more
@@ -680,11 +704,11 @@
  *  \param blend_to_black Uses Alpha to blend buffer to black
  *  \param threshold      Alpha threshold above which to perform blending
  */
-void OSDSurface::BlendToARGB(unsigned char *argbptr, uint stride, 
+void YUVSurface::BlendToARGB(unsigned char *argbptr, uint stride,
                              uint outheight, bool blend_to_black,
                              uint threshold) const
 {
-    const OSDSurface *surface = this;
+    const YUVSurface *surface = this;
     blendtoargb_8_fun blender = blendtoargb_8_init(surface);
     const unsigned char *cm = surface->cm;
 
@@ -756,8 +780,8 @@
         BlendToBlack(argbptr, stride>>2, outheight);
 }
 
-/** \fn OSDSurface::DitherToI44(unsigned char*,bool,uint,uint) const
- *  \brief Copies and converts OSDSurface to either a greyscale
+/** \fn YUVSurface::DitherToI44(unsigned char*,bool,uint,uint) const
+ *  \brief Copies and converts YUVSurface to either a greyscale
  *         IA44 or AI44 buffer.
  *  \sa DitherToIA44(unsigned char*,uint,uint) const,
  *      DitherToAI44(unsigned char*,uint,uint) const.
@@ -767,10 +791,10 @@
  *  \param stride Length of each line in output buffer in bytes
  *  \param outheight Number of lines in output buffer
  */
-void OSDSurface::DitherToI44(unsigned char *outbuf, bool ifirst,
+void YUVSurface::DitherToI44(unsigned char *outbuf, bool ifirst,
                              uint stride, uint outheight) const
 {
-    const OSDSurface *surface = this;
+    const YUVSurface *surface = this;
     int ashift = ifirst ? 0 : 4;
     int amask = ifirst ? 0x0f : 0xf0;
 
@@ -855,8 +879,8 @@
     delete_dithertoia44_8_context(dcontext);
 }
 
-/** \fn OSDSurface::DitherToIA44(unsigned char*,uint,uint) const
- *  \brief Copies and converts OSDSurface to a greyscale IA44 buffer.
+/** \fn YUVSurface::DitherToIA44(unsigned char*,uint,uint) const
+ *  \brief Copies and converts YUVSurface to a greyscale IA44 buffer.
  *
  *  \param outbuf Output buffer
  *  \param stride Length of each line in output buffer in bytes
@@ -864,14 +888,14 @@
  *  \sa DitherToI44(unsigned char*,bool,uint,uint) const,
  *      DitherToAI44(unsigned char*,uint,uint) const.
  */
-void OSDSurface::DitherToIA44(unsigned char* outbuf,
+void YUVSurface::DitherToIA44(unsigned char* outbuf,
                               uint stride, uint outheight) const
 {
     DitherToI44(outbuf, false, stride, outheight);
 }
 
-/** \fn OSDSurface::DitherToAI44(unsigned char*,bool,uint,uint) const
- *  \brief Copies and converts OSDSurface to a greyscale AI44 buffer.
+/** \fn YUVSurface::DitherToAI44(unsigned char*,bool,uint,uint) const
+ *  \brief Copies and converts YUVSurface to a greyscale AI44 buffer.
  *
  *  \param outbuf Output buffer
  *  \param stride Length of each line in output buffer in bytes
@@ -879,8 +903,38 @@
  *  \sa DitherToI44(unsigned char*,bool,uint,uint) const,
  *      DitherToIA44(unsigned char*,uint,uint) const.
  */
-void OSDSurface::DitherToAI44(unsigned char* outbuf,
+void YUVSurface::DitherToAI44(unsigned char* outbuf,
                               uint stride, uint outheight) const
 {
     DitherToI44(outbuf, true, stride, outheight);
 }
+
+I44Surface::I44Surface(int w, int h) :
+    OSDSurface(w,h)
+{
+    i44buffer = new unsigned char [size];
+    Clear();
+}
+
+I44Surface::~I44Surface()
+{
+    delete [] i44buffer;
+}
+
+void I44Surface::Clear(void)
+{
+    bzero(i44buffer, size);
+    OSDSurface::Clear();
+}
+
+void I44Surface::ClearUsed(void)
+{
+    bzero(i44buffer, size);
+    OSDSurface::Clear();
+}
+
+void I44Surface::BlendToI44(unsigned char *i44ptr, bool /*ifirst*/,
+                            uint /*stride*/, uint /*height*/) const
+{
+    memcpy(i44ptr, i44buffer, size);
+}
Index: libs/libmythtv/ttfont.cpp
===================================================================
--- libs/libmythtv/ttfont.cpp	(revision 7651)
+++ libs/libmythtv/ttfont.cpp	(working copy)
@@ -31,11 +31,18 @@
 #include "osdtypes.h"
 #include "osdsurface.h"
 
+#include <sys/time.h>
+
+#ifdef TIMING
+#include "timer.h"
+#endif
+
 static int          have_library = 0;
 static FT_Library   the_library;
 
 #define FT_VALID(handle) ((handle) && (handle)->clazz != NULL)
 
+#if 0
 struct Raster_Map
 {
     int width;
@@ -44,10 +51,12 @@
     int size;
     unsigned char *bitmap;
 };
+#endif
 
 void TTFFont::setColor(int color)
 {
     color %= 256;
+    m_color_normal = color;
     m_color_normal_y = color;
     m_color_normal_u = m_color_normal_v = 128;
 
@@ -80,18 +89,21 @@
             m_color_normal_y = (uint8_t)(y);
             m_color_normal_u = (uint8_t)(127 + u);
             m_color_normal_v = (uint8_t)(127 + v);
+            m_color_normal = k;
             break;
 
         case kTTF_Outline:
             m_color_outline_y = (uint8_t)(y);
             m_color_outline_u = (uint8_t)(127 + u);
             m_color_outline_v = (uint8_t)(127 + v);
+            m_color_outline = k;
             break;
 
         case kTTF_Shadow:
             m_color_shadow_y = (uint8_t)(y);
             m_color_shadow_u = (uint8_t)(127 + u);
             m_color_shadow_v = (uint8_t)(127 + v);
+            m_color_shadow = k;
             break;
     }
 }
@@ -103,8 +115,8 @@
    rmap = new Raster_Map;
    rmap->width = (width + 3) & -4;
    rmap->rows = height;
-   rmap->cols = rmap->width;
-   rmap->size = rmap->rows * rmap->width;
+   rmap->cols = (m_mono) ? (rmap->width+7) >> 3 : rmap->width;
+   rmap->size = rmap->rows * rmap->cols;
    if (rmap->size <= 0)
    {
         delete rmap;
@@ -202,6 +214,10 @@
 void TTFFont::render_text(Raster_Map *rmap, Raster_Map *rchr,
 	                  const QString &text, int *xorblah, int *yor)
 {
+#ifdef TIMING
+    Timer t("render_text");
+#endif
+
    FT_F26Dot6 x, y, xmin, ymin, xmax, ymax;
    FT_BBox bbox;
    unsigned int i, ioff, iread;
@@ -248,7 +264,9 @@
            origin.x = 0;
            origin.y = 0;
 
-           FT_Glyph_To_Bitmap(&glyphs[j], ft_render_mode_normal, &origin, 1);
+           FT_Render_Mode rmode;
+           rmode = m_mono ? ft_render_mode_mono : ft_render_mode_normal;
+           FT_Glyph_To_Bitmap(&glyphs[j], rmode, &origin, 1);
            bmap = (FT_BitmapGlyph)(glyphs[j]);
 
            glyphs_cached[j] = duplicate_raster(bmap);
@@ -311,13 +329,15 @@
        if (ymax >= rmap->rows)
            ymax = rmap->rows - 1;
 
+       int x_ioff = 0, x_iread=0;
+
        if (xmin < 0)
        {
-           iread -= xmin;
+           x_iread = -xmin;
            xmin = 0;
        }
        else
-           ioff += xmin;
+           x_ioff = xmin;
 
        if (xmax >= rmap->width)
            xmax = rmap->width - 1;
@@ -327,17 +347,59 @@
        _read = (char *)rtmp->bitmap + iread;
        _off = (char *)rmap->bitmap + ioff;
 
+       int len = xmax - xmin;
+       int bytes = len >> 3;
+
+       int x_off = x_ioff;
+
+       unsigned char last=0, next=0;
+       unsigned char lmask,nmask=255;
+
+       int bit_off = x_off&7;
+
+       nmask = nmask >> bit_off;
+       lmask = 255 ^ nmask;
+
        for (y = ymin; y <= ymax; y++)
        {
            read = _read;
            off = _off;
 
-           for (x = xmin; x <= xmax; x++)
+           if (m_mono)
            {
-	       *off = *read;
-               off++;
-               read++;
+               off += (x_off>>3);
+
+               int i;
+               last = *off;
+               for (i=0; i<=bytes; i++)
+               {
+                   __asm__ __volatile__ (
+                       "movb %b1, %b0; rorb %b2,%b0"
+                       : "=a"(next):"g"(*read++),"c"(bit_off));
+                
+                   *off++ = (last & lmask)|(next & nmask);
+
+                   last=next;
+               }
+               if (bit_off)
+                   *off |= last & lmask;
+
+// i 16, j 't' xmin 180, xmax 186, x_iread 0, x_ioff 180 iread 34 ioff 594
+// i 17, j 'c' xmin 188, xmax 197, x_iread 0, x_ioff 188 iread 24 ioff 594
+// i 18, j 'h' xmin 201, xmax 210, x_iread 0, x_ioff 201 iread 34 ioff 594
            }
+           else
+           {
+               read += x_iread;
+               off += x_ioff;
+
+               for (x = xmin; x <= xmax; x++)
+               {
+                   *off = *read;
+                   off++;
+                   read++;
+               }
+           }
            _read -= rtmp->cols;
            _off -= rmap->cols;
        }
@@ -349,10 +411,92 @@
     }
 }
 
-void TTFFont::merge_text(OSDSurface *surface, Raster_Map * rmap, int offset_x, 
+void TTFFont::merge_text(I44Surface *surface, Raster_Map * rmap, int offset_x, 
                          int offset_y, int xstart, int ystart, int width, 
                          int height, int alphamod, kTTF_Color k)
 {
+#ifdef TIMING
+    Timer t("merge_text i44");
+#endif
+
+    unsigned char *asrc, *adst;
+    if (xstart < 0)
+    {
+        width += xstart;
+        offset_x -= xstart;
+        xstart = 0;
+    }
+
+    if (ystart < 0)
+    {
+        height += ystart;
+        offset_y -= ystart;
+        ystart = 0;
+    }
+
+    if (height + ystart > surface->height)
+        height = surface->height - ystart;
+
+    if (width + xstart > surface->width)
+        width = surface->width - xstart;
+
+    QRect drawRect(xstart, ystart, width, height);
+    surface->AddRect(drawRect);
+
+    int x, y;
+
+    asrc = rmap->bitmap;
+    adst = surface->i44buffer;
+
+    asrc += rmap->cols*offset_y+(offset_x>>3);
+    adst += xstart+ystart*surface->width;
+
+    unsigned long col;
+    switch(k)
+    {
+        case kTTF_Normal:
+                 col = (m_color_normal&0xf)<<4;
+            break;
+        case kTTF_Outline:
+                 col = (m_color_outline&0xf)<<4;
+            break;
+        case kTTF_Shadow:
+                 col = (m_color_shadow&0xf)<<4;
+            break;
+    }
+
+    if (alphamod>255)
+        alphamod = 255;
+    col |= alphamod>>4;
+
+    for (y = 0; y<height;y++)
+    {
+        char ch;
+        int j = 0;
+
+        for (x = 0; x<width;x++)
+        {
+            if ((x&7) == 0)
+            {
+                ch = asrc[j++];
+            }
+            else
+            {
+                ch = ch<<1;
+            }
+
+            if (ch & 0x80)
+                adst[x] = col;// | 0x0f;
+        }
+        asrc += rmap->cols;
+        adst += surface->width;
+    }
+}
+
+void TTFFont::merge_text(YUVSurface *surface, Raster_Map * rmap, int offset_x, 
+                         int offset_y, int xstart, int ystart, int width, 
+                         int height, int alphamod, kTTF_Color k)
+{
     unsigned char * asrc, * ydst, * udst, * vdst, * adst;
     uint8_t color_y = 0, color_u = 0, color_v = 0;
 
@@ -411,16 +555,17 @@
                                surface->pow_lut);
 }
 
-void TTFFont::DrawString(OSDSurface *surface, int x, int y, 
-                         const QString &text, int maxx, int maxy, 
-                         int alphamod)
+Raster_Map* TTFFont::Prerender(const QString &text)
 {
-   int                  width, height, w, h, inx, iny, clipx, clipy;
-   Raster_Map          *rmap, *rtmp;
-   char                 is_pixmap = 0;
+#ifdef TIMING
+    Timer t("Prerender");
+#endif
+   int inx, iny, w, h; 
+   Raster_Map   *rmap, *rtmp;
+   char         is_pixmap = 0;
 
    if (text.length() < 1)
-        return;
+        return 0;
 
    inx = 0;
    iny = 0;
@@ -429,7 +574,7 @@
    if (w <= 0 || h <= 0)
    {
        destroy_font_raster(rtmp);
-       return;
+       return 0;
    }
    rmap = create_font_raster(w, h);
 
@@ -437,6 +582,43 @@
 
    is_pixmap = 1;
 
+    rmap->m_w = w;
+    rmap->m_h = h;
+    rmap->m_inx = inx;
+    rmap->m_iny = iny;
+
+return rmap;
+}
+
+void TTFFont::DrawString(OSDSurface *surface, int x, int y, 
+                         const QString &text, int maxx, int maxy, 
+                         int alphamod )
+{
+#ifdef TIMING
+    Timer t("DrawString");
+#endif
+    Raster_Map          *rmap;
+
+    int width, height, w, h, inx, iny, clipx, clipy;
+
+    if (rasters.contains(text))
+    {
+        rmap = rasters[text];
+    }
+    else
+    {
+        rmap = Prerender(text);
+        rasters[text] = rmap;
+    }
+
+    if (!rmap)
+        return;
+
+    w = rmap->m_w;
+    h = rmap->m_h;
+    inx = rmap->m_inx;
+    iny = rmap->m_iny;
+   
    y += loadedfontsize;
    
    width = maxx;
@@ -470,41 +652,82 @@
      }
    if ((width <= 0) || (height <= 0))
      {
-	destroy_font_raster(rmap);
-	destroy_font_raster(rtmp);
-	return;
+         return;
      }
 
    if (m_shadowxoff > 0 || m_shadowyoff > 0)
    {
-       merge_text(surface, rmap, clipx, clipy, x + m_shadowxoff,
-                  y + m_shadowyoff, width, height, alphamod, kTTF_Shadow);
+       if (surface->SurfaceType() == OSDSurface::SURF_YUV)
+       {
+           merge_text((YUVSurface*)surface, rmap, clipx, clipy,
+                      x + m_shadowxoff, y + m_shadowyoff,
+                      width, height, alphamod, kTTF_Shadow);
+       }
+       else if (surface->SurfaceType() == OSDSurface::SURF_I44)
+       {
+           merge_text((I44Surface*)surface, rmap, clipx, clipy,
+                      x + m_shadowxoff, y + m_shadowyoff,
+                      width, height, alphamod, kTTF_Shadow);
+       }
    }
 
    if (m_outline)
    {
-       merge_text(surface, rmap, clipx, clipy, x - 1, y - 1, width, height,
-                  alphamod, kTTF_Outline);
-       merge_text(surface, rmap, clipx, clipy, x + 1, y - 1, width, height,
-                  alphamod, kTTF_Outline);
-       merge_text(surface, rmap, clipx, clipy, x - 1, y + 1, width, height,
-                  alphamod, kTTF_Outline);
-       merge_text(surface, rmap, clipx, clipy, x + 1, y + 1, width, height,
-                  alphamod, kTTF_Outline);
+       if (surface->SurfaceType() == OSDSurface::SURF_YUV)
+       {
+           merge_text((YUVSurface*)surface, rmap, clipx, clipy,
+                      x - 1, y - 1, width, height,
+                      alphamod, kTTF_Outline);
+           merge_text((YUVSurface*)surface, rmap, clipx, clipy,
+                      x + 1, y - 1, width, height,
+                      alphamod, kTTF_Outline);
+           merge_text((YUVSurface*)surface, rmap, clipx, clipy,
+                      x - 1, y + 1, width, height,
+                      alphamod, kTTF_Outline);
+           merge_text((YUVSurface*)surface, rmap, clipx, clipy,
+                      x + 1, y + 1, width, height,
+                      alphamod, kTTF_Outline);
+       }
+       else if (surface->SurfaceType() == OSDSurface::SURF_I44)
+       {
+           merge_text((I44Surface*)surface, rmap, clipx, clipy,
+                      x - 1, y - 1, width, height,
+                      alphamod, kTTF_Outline);
+           merge_text((I44Surface*)surface, rmap, clipx, clipy,
+                      x + 1, y - 1, width, height,
+                      alphamod, kTTF_Outline);
+           merge_text((I44Surface*)surface, rmap, clipx, clipy,
+                      x - 1, y + 1, width, height,
+                      alphamod, kTTF_Outline);
+           merge_text((I44Surface*)surface, rmap, clipx, clipy,
+                      x + 1, y + 1, width, height,
+                      alphamod, kTTF_Outline);
+
+       }
    }
 
-   merge_text(surface, rmap, clipx, clipy, x, y, width, height, alphamod);
-
-   destroy_font_raster(rmap);
-   destroy_font_raster(rtmp);
+   if (surface->SurfaceType() == OSDSurface::SURF_YUV)
+   {
+       merge_text((YUVSurface*)surface, rmap, clipx, clipy,
+                  x, y, width, height, alphamod);
+   }
+   else if (surface->SurfaceType() == OSDSurface::SURF_I44)
+   {
+       merge_text((I44Surface*)surface, rmap, clipx, clipy,
+                  x, y, width, height, alphamod);
+   }
 }
 
 TTFFont::~TTFFont()
 {
-   if (!valid)
-       return;
+    QMap<QString,Raster_Map*>::Iterator it;
+    for (it = rasters.begin(); it != rasters.end(); ++it)
+        destroy_font_raster(*it);
 
-   KillFace();
+    if (!valid)
+        return;
+
+    KillFace();
 }
 
 void TTFFont::KillFace(void)
@@ -526,7 +749,7 @@
 }
 
 TTFFont::TTFFont(char *file, int size, int video_width, int video_height,
-                 float hmult)
+                 float hmult, bool mono)
 {
    FT_Error            error;
 
@@ -534,17 +757,21 @@
    m_size = size;
    spacewidth = 0;
 
+   m_mono = mono;
    m_outline = false;
    m_shadowxoff = 0;
    m_shadowyoff = 0;
 
    m_color_normal_y = 255;
+   m_color_normal = 255;
    m_color_normal_u = m_color_normal_v = 128;
 
    m_color_outline_y = 0x40;
+   m_color_outline = 0x40;
    m_color_outline_u = m_color_outline_v = 128;
 
    m_color_shadow_y = 0x20;
+   m_color_shadow = 0x20;
    m_color_shadow_u = m_color_shadow_v = 128;
 
    if (!have_library)
Index: libs/libmythtv/osd.cpp
===================================================================
--- libs/libmythtv/osd.cpp	(revision 7651)
+++ libs/libmythtv/osd.cpp	(working copy)
@@ -29,8 +29,9 @@
 
 OSD::OSD(int width, int height, int frint,
          int dispx, int dispy, int dispw, int disph)
-   : QObject()
+   : QObject(NULL, "osd")
 {
+    hasPalette = false;
     changed = false;
     vid_width = width;
     vid_height = height;
@@ -75,7 +76,10 @@
 
     SetDefaults();
 
-    drawSurface = new OSDSurface(width, height);
+    if (surftype == "I44")
+        drawSurface = new I44Surface(width, height);
+    else //default to normal YUV
+        drawSurface = new YUVSurface(width, height);
 }
 
 OSD::~OSD(void)
@@ -245,8 +249,12 @@
     }
 
     delete drawSurface;
-    drawSurface = new OSDSurface(width, height);
 
+    if (surftype == "I44")
+        drawSurface = new I44Surface(width, height);
+    else //default to normal YUV
+        drawSurface = new YUVSurface(width, height);
+
     osdlock.unlock();
 }
 
@@ -274,8 +282,9 @@
 TTFFont *OSD::LoadFont(QString name, int size)
 {
     QString fullname = MythContext::GetConfDir() + "/" + name;
+    bool mono = (surftype == "I44");
     TTFFont *font = new TTFFont((char *)fullname.ascii(), size, vid_width,
-                                vid_height, hmult);
+                                vid_height, hmult, mono);
 
     if (font->isValid())
         return font;
@@ -284,7 +293,7 @@
     fullname = gContext->GetShareDir() + name;
 
     font = new TTFFont((char *)fullname.ascii(), size, vid_width,
-                       vid_height, hmult);
+                       vid_height, hmult, mono);
 
     if (font->isValid())
         return font;
@@ -294,7 +303,7 @@
     {
         fullname = themepath + "/" + name;
         font = new TTFFont((char *)fullname.ascii(), size, vid_width,
-                           vid_height, hmult);
+                           vid_height, hmult, mono);
         if (font->isValid())
             return font;
     }
@@ -303,7 +312,7 @@
 
     fullname = name;
     font = new TTFFont((char *)fullname.ascii(), size, vid_width, vid_height,
-                       hmult);
+                       hmult, mono);
 
     if (font->isValid())
         return font;
@@ -327,6 +336,39 @@
     return "";
 }
 
+void OSD::parsePalette(QDomElement &element)
+{
+    hasPalette = true;
+
+    for (QDomNode child = element.firstChild(); !child.isNull();
+         child = child.nextSibling())
+    {
+        QDomElement node = child.toElement();
+
+        if (node.isNull())
+            continue;
+
+        if (node.tagName() != "rgb")
+        {
+            VERBOSE(VB_IMPORTANT, QString("Unknown tag '%1' in colour node")
+                    .arg(node.tagName()));
+            continue;
+        }
+
+        int r, g, b;
+        QString text = getFirstText(node);
+        if (sscanf(text.data(), "%d,%d,%d", &r, &g, &b) != 3)
+        {
+            VERBOSE(VB_IMPORTANT, QString("Badly formed rgb node '%1'")
+                    .arg(text.data()));
+            continue;
+        }
+
+        // Success! Add new color to the palette.
+        surfPalette.append(QColor(r,g,b));
+    }
+}
+
 void OSD::parseFont(QDomElement &element)
 {
     QString name;
@@ -1196,6 +1238,15 @@
             {
                 parseContainer(e);
             }
+            else if (e.tagName() == "surface")
+            {
+                surftype = getFirstText(e);
+            }
+            else if (e.tagName() == "palette")
+            {
+                parsePalette(e);
+		OSDTypeImage::SetPalette(surfPalette);
+            }
             else
             {
                 VERBOSE(VB_IMPORTANT, "Unknown element: " << e.tagName());
Index: libs/libmythtv/osdsurface.h
===================================================================
--- libs/libmythtv/osdsurface.h	(revision 7651)
+++ libs/libmythtv/osdsurface.h	(working copy)
@@ -18,11 +18,16 @@
 class OSDSurface
 {
   public:
+    enum SURFTYPE{
+    SURF_YUV,
+    SURF_I44
+    };
+
     OSDSurface(int w, int h);
-   ~OSDSurface();
+    virtual ~OSDSurface();
 
-    void Clear(void);
-    void ClearUsed(void);
+    virtual void Clear(void);
+    virtual void ClearUsed(void);
 
     bool IntersectsDrawn(QRect &newrect);
     void AddRect(QRect &newrect);
@@ -35,7 +40,48 @@
             ++revision;
     }
     int GetRevision() { return revision; }
+    int revision;
 
+    virtual SURFTYPE SurfaceType() = 0;
+
+    int width;
+    int height;
+    int size;
+
+    QRegion usedRegions;
+    bool changed;
+};
+
+class I44Surface : public OSDSurface
+{
+public:        
+    I44Surface(int w, int h);
+    ~I44Surface();
+
+    virtual void Clear(void);
+    virtual void ClearUsed(void);
+    
+    SURFTYPE SurfaceType() { return SURF_I44; }
+    
+    unsigned char *i44buffer;
+
+    void BlendToI44(unsigned char* outbuf, bool ifirst, uint stride, uint height) const;
+private:
+};
+
+
+class YUVSurface : public OSDSurface
+{
+  public:
+    YUVSurface(int w, int h);
+   ~YUVSurface();
+    
+    SURFTYPE SurfaceType() { return SURF_YUV; }
+
+    virtual void Clear(void);
+    virtual void ClearUsed(void);
+
+
     void BlendToYV12(unsigned char *yuvptr) const;
     void BlendToARGB(unsigned char *argbptr,
                      uint stride, uint height, bool blendtoblack=false,
@@ -45,8 +91,6 @@
     void DitherToIA44(unsigned char* outbuf, uint stride, uint height) const;
     void DitherToAI44(unsigned char* outbuf, uint stride, uint height) const;
 
-    int revision;
-
     unsigned char *yuvbuffer;
 
     // just pointers into yuvbuffer
@@ -56,12 +100,6 @@
 
     unsigned char *alpha;
 
-    int width;
-    int height;
-    int size;
-
-    QRegion usedRegions;
-
 #ifdef MMX
     short int rec_lut[256];
 #else
@@ -75,8 +113,6 @@
     blendcolor_ptr blendcolorfunc;
     blendconst_ptr blendconstfunc;
 
-    bool changed;
-
     bool usemmx;
 
     unsigned char cropTbl[256 + 2 * MAX_NEG_CROP];
@@ -86,13 +122,13 @@
 typedef void (*blendtoyv12_8_fun)(unsigned char *src, unsigned char *dest,
                                   unsigned char *alpha, bool uvplane);
 
-blendtoyv12_8_fun blendtoyv12_8_init(const OSDSurface *surface);
+blendtoyv12_8_fun blendtoyv12_8_init(const YUVSurface *surface);
 
-typedef void (*blendtoargb_8_fun)(const OSDSurface *surf, unsigned char *src, 
+typedef void (*blendtoargb_8_fun)(const YUVSurface *surf, unsigned char *src, 
                                   unsigned char *usrc, unsigned char *vsrc, 
                                   unsigned char *alpha, unsigned char *dest);
 
-blendtoargb_8_fun blendtoargb_8_init(const OSDSurface *surface);
+blendtoargb_8_fun blendtoargb_8_init(const YUVSurface *surface);
            
 
 struct dither8_context;
@@ -102,7 +138,7 @@
                                    const unsigned char *dmp, int xpos,
                                    dither8_context *context);
 
-dithertoia44_8_fun dithertoia44_8_init(const OSDSurface *surface);
+dithertoia44_8_fun dithertoia44_8_init(const YUVSurface *surface);
 dither8_context *init_dithertoia44_8_context(bool first);
 void delete_dithertoia44_8_context(dither8_context *context);
 
Index: libs/libmythtv/ttfont.h
===================================================================
--- libs/libmythtv/ttfont.h	(revision 7651)
+++ libs/libmythtv/ttfont.h	(working copy)
@@ -17,6 +17,8 @@
 
 struct Raster_Map;
 class OSDSurface;
+class YUVSurface;
+class I44Surface;
 
 enum kTTF_Color {
     kTTF_Normal = 0, 
@@ -24,11 +26,24 @@
     kTTF_Shadow,
 };
 
+struct Raster_Map
+{
+    int width;
+    int rows;
+    int cols;
+    int size;
+    unsigned char *bitmap;
+    int m_w;
+    int m_h;
+    int m_inx;
+    int m_iny;
+};
+
 class TTFFont
 {
   public:
      TTFFont(char *file, int size, int video_width, int video_height,
-             float hmult);
+             float hmult, bool mono);
     ~TTFFont();
 
      // Actually greyscale, keep for compat.
@@ -41,6 +56,7 @@
 
      bool isValid(void) { return valid; }
 
+     Raster_Map* Prerender(const QString &text );
      void DrawString(OSDSurface *surface, int x, int y, const QString &text,
                      int maxx, int maxy, int alphamod = 255); 
      void CalcWidth(const QString &text, int *width_return);
@@ -50,6 +66,8 @@
 
      void Reinit(int width, int height, float hmult);
 
+     static void destroy_font_raster(Raster_Map *rmap);
+
   private:
      void KillFace(void);
      void Init(void);
@@ -57,13 +75,15 @@
      Raster_Map *create_font_raster(int width, int height);
      Raster_Map *duplicate_raster(FT_BitmapGlyph bmap);
      void clear_raster(Raster_Map *rmap);
-     void destroy_font_raster(Raster_Map *rmap);
      Raster_Map *calc_size(int *width, int *height, const QString &text);
      void render_text(Raster_Map *rmap, Raster_Map *rchr, const QString &text, 
-                      int *xorblah, int *yor);
-     void merge_text(OSDSurface *surface, Raster_Map *rmap, int offset_x, 
+                      int *xorblah, int *yor );
+     void merge_text(YUVSurface *surface, Raster_Map *rmap, int offset_x, 
                      int offset_y, int xstart, int ystart, int width, 
                      int height, int alphamod, kTTF_Color k = kTTF_Normal);
+     void merge_text(I44Surface *surface, Raster_Map *rmap, int offset_x, 
+                     int offset_y, int xstart, int ystart, int width, 
+                     int height, int alphamod, kTTF_Color k = kTTF_Normal);
      bool cache_glyph(unsigned short c);
 
      bool         valid;
@@ -88,19 +108,27 @@
      uint8_t m_color_normal_y;
      uint8_t m_color_normal_u;
      uint8_t m_color_normal_v;
+     uint8_t m_color_normal;
 
      uint8_t m_color_outline_y;
      uint8_t m_color_outline_u;
      uint8_t m_color_outline_v;
+     uint8_t m_color_outline;
 
      uint8_t m_color_shadow_y;
      uint8_t m_color_shadow_u;
      uint8_t m_color_shadow_v;
+     uint8_t m_color_shadow;
 
      QString m_file;
 
      int loadedfontsize;
      float m_hmult;
+    
+    bool m_mono;
+
+    QMap<QString, Raster_Map *> rasters;
+
 };
 
 #endif
