Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.cpp	(revision 6809)
+++ libs/libmythtv/NuppelVideoPlayer.cpp	(working copy)
@@ -1878,7 +1878,7 @@
                       dispx, dispy, dispw, disph);
 
         if (kCodec_NORMAL_END < decoder->GetVideoCodecID() &&
-            kCodec_SPECIAL_END > decoder->GetVideoCodecID() &&
+            kCodec_STD_XVMC_END > decoder->GetVideoCodecID() &&
             (600 < video_height))
         {            
             osd->DisableFade();
Index: libs/libmythtv/osd.h
===================================================================
--- libs/libmythtv/osd.h	(revision 6809)
+++ libs/libmythtv/osd.h	(working copy)
@@ -121,6 +121,8 @@
                                   OSDGenericTree *treeToShow);
 
     void DisableFade(void);
+    bool HasPalette() { return hasPalette; }
+    const QValueList<QColor>& Palette() { return surfPalette; }
 
  private:
     void SetDefaults();
@@ -149,6 +151,8 @@
     void parsePositionImage(OSDSet *container, QDomElement &element);
     void parseListTree(OSDSet *container, QDomElement &element);
 
+    void parsePalette(QDomElement &element);
+        
     int vid_width;
     int vid_height;
     int frameint;
@@ -178,6 +182,10 @@
     OSDTypeImage *editarrowright;
     QRect editarrowRect;
 
+    QString surftype;
+    QValueList<QColor> surfPalette;
+    bool hasPalette;
+    
     OSDSurface *drawSurface;
     bool changed;
 
Index: libs/libmythtv/osdtypes.cpp
===================================================================
--- libs/libmythtv/osdtypes.cpp	(revision 6809)
+++ libs/libmythtv/osdtypes.cpp	(working copy)
@@ -14,6 +14,53 @@
 
 #include "mythcontext.h"
 
+#include <sys/time.h>
+
+#ifdef TIMING
+#include "timer.h"
+
+int Timer::indent = 0;
+Timer::Timer(const QString &title)
+{
+    name = title;
+    gettimeofday(&start,NULL);
+
+    int i;
+    for (i=0;i<indent;i++)
+        cout << "  ";
+    indent ++;
+    cout << name << " timing.." << endl;
+}
+
+Timer::~Timer()
+{
+    struct timeval dur;
+    gettimeofday(&end,NULL);
+
+    timersub(&end, &start, &dur);
+
+    indent--; 
+    int i;
+    for (i=0;i<indent;i++)
+        cout << "  ";
+ 
+    cout << name << " time " << dur.tv_usec << endl;
+}
+
+void Timer::check(const QString &tag)
+{
+    struct timeval dur,now;
+    gettimeofday(&now,NULL);
+
+    timersub(&now, &start, &dur);
+
+    int i;
+    for (i=0;i<indent;i++)
+        cout << "  ";
+    cout << tag << " time " << dur.tv_usec << endl;
+}
+#endif
+
 OSDSet::OSDSet(const QString &name, bool cache, int screenwidth, 
                int screenheight, float wmult, float hmult, int frint)
       : QObject()
@@ -361,6 +408,10 @@
 
 void OSDSet::Draw(OSDSurface *surface, bool actuallydraw)
 {
+#ifdef TIMING
+Timer t("OSDSet::Draw");
+#endif
+
     if (actuallydraw)
     {
         vector<OSDType *>::iterator i = allTypes->begin();
@@ -437,7 +488,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;
@@ -457,10 +508,14 @@
     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;
@@ -480,6 +535,11 @@
 
 OSDTypeText::~OSDTypeText()
 {
+    if (m_raster)
+    {
+       TTFFont::destroy_font_raster(m_raster);
+       m_raster=0;
+    }      
 }
 
 void OSDTypeText::SetAltFont(TTFFont *font)
@@ -489,19 +549,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);
@@ -513,6 +597,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)
@@ -524,17 +611,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;
 
@@ -652,6 +739,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;
@@ -707,6 +798,8 @@
     m_isvalid = false;
     m_imagesize = QRect(0, 0, 0, 0);
 
+    m_i44 = NULL;
+
     m_scalew = scalew;
     m_scaleh = scaleh;
 
@@ -728,6 +821,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;
@@ -743,7 +838,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)
@@ -761,6 +860,8 @@
     m_vbuffer = NULL;
     m_isvalid = false;
     m_filename = "";
+
+    m_i44 = NULL;
 }
 
 OSDTypeImage::OSDTypeImage(void)
@@ -779,6 +880,8 @@
     m_vbuffer = NULL;
     m_isvalid = false;
     m_filename = "";
+
+    m_i44 = NULL;
 }
 
 OSDTypeImage::~OSDTypeImage()
@@ -787,6 +890,9 @@
         delete [] m_yuv;
     if (m_alpha)
         delete [] m_alpha;
+
+    if (m_i44)
+        delete [] m_i44;
 }
 
 void OSDTypeImage::SetName(const QString &name)
@@ -805,6 +911,60 @@
     LoadImage(m_filename, wmult, hmult, m_scalew, m_scaleh);
 }
 
+void rgb32_to_i44(unsigned char*i44, unsigned char*rgb, int width, int height, int srcwidth)
+{
+    int wrap, wrap4, x, y;
+    unsigned char *p;
+    unsigned char ch,r,g,b;
+   
+printf("rgb32_to_i44\n");
+ 
+    p = rgb;
+
+    for (y=0; y<height; y++)
+    {
+        unsigned char *pstart=p;
+        
+        for (x=0; x<width; x++)
+        {
+
+// 0 0 0 0 . . . .  // alpha
+// . . . . 0 x x x  // greys 
+// . . . . 1 0 0 0  // 
+// . . . . 1 0 0 1  // red
+// . . . . 1 0 1 0  // green
+// . . . . 1 0 1 1  // yellow
+// . . . . 1 1 0 0  // blue
+// . . . . 1 1 0 1  // magen
+// . . . . 1 1 1 0  // cyan
+// . . . . 1 1 1 1  // 
+
+            ch = (p[3] >> 4) & 0x0f; //trunc alpha
+            r=p[2]; g=p[1]; b=p[0];
+
+            if ((r == g) && (g == b)) //lets have 8 greys
+            {
+                ch |= ((r>>1) & 0x70);
+//                ch |= 0x0b;
+            }
+            else // ok now try and grab colours
+            { // trivial func for now.
+                ch |= 0x80;
+              if (r>128) ch |= 0x10;
+              if (g>128) ch |= 0x20;
+              if (b>128) ch |= 0x40;
+            }
+
+            *(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)
 {
@@ -815,9 +975,14 @@
         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)
@@ -856,9 +1021,15 @@
 
     m_alpha = new unsigned char[imwidth * imheight];
 
+    m_i44 = new unsigned char[imwidth*imheight];
+
+printf("yuv convert\n");
+
     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());
+
     m_imagesize = QRect(0, 0, imwidth, imheight);
 }
 
@@ -871,9 +1042,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;
@@ -888,13 +1063,28 @@
 
     m_alpha = new unsigned char[imwidth * imheight];
 
+    m_i44 = new unsigned char[imwidth*imheight];
+
     rgb32_to_yuv420p(m_ybuffer, m_ubuffer, m_vbuffer, m_alpha, img.bits(),
                      imwidth, imheight, img.width());
 
+    rgb32_to_i44(m_i44, img.bits(), imwidth, imheight, img.width());
     m_imagesize = QRect(0, 0, imwidth, imheight);
 }
 
-void OSDTypeImage::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, 
+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)
@@ -902,6 +1092,116 @@
 
     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;
+
+    unsigned char *dest, *destalpha, *src, *srcalpha;
+    unsigned char *udest, *vdest, *usrc, *vsrc;
     int alpha, iwidth, drawwidth;
 
     iwidth = drawwidth = m_imagesize.width();
@@ -1282,6 +1582,14 @@
 
 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;
@@ -1405,8 +1713,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);
@@ -1427,6 +1749,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;
 
@@ -1549,10 +1921,22 @@
     positions.push_back(rect);
     m_numpositions++;
 }
-
 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;
@@ -1622,6 +2006,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 6809)
+++ libs/libmythtv/videooutbase.cpp	(working copy)
@@ -1105,13 +1105,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:
@@ -1146,6 +1150,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 6809)
+++ 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
@@ -212,6 +216,8 @@
     bool m_scrollinit;
 
     float m_linespacing;
+
+    Raster_Map *m_raster;
 };
     
 class OSDTypeImage : public OSDType
@@ -245,6 +251,10 @@
 
     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);
 
   protected:
     QRect m_imagesize;
@@ -261,7 +271,10 @@
 
     unsigned char *m_alpha;
 
+    unsigned char *m_i44;
+
     int m_scalew, m_scaleh;
+    float m_wmult, m_hmult;
 
     int m_drawwidth;
     bool m_onlyusefirst;
@@ -331,6 +344,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;
@@ -363,6 +378,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;
@@ -403,6 +420,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 6809)
+++ libs/libmythtv/videoout_xv.cpp	(working copy)
@@ -2415,6 +2415,13 @@
     XvMCOSD* xvmc_osd = GetAvailableOSD();
     if (osd && xvmc_osd->IsValid())
     {
+        if (osd->HasPalette() && 
+            !xvmc_osd->CustomPalette())
+        {
+            VERBOSE(VB_IMPORTANT, "Setting palette");
+            xvmc_osd->SetPalette(osd->Palette());
+        }
+
         VideoFrame *osdframe = NULL;
         int ret = DisplayOSD(xvmc_osd->OSDFrame(), osd, -1,
                              xvmc_osd->GetRevision());
Index: libs/libmythtv/osdxvmc.h
===================================================================
--- libs/libmythtv/osdxvmc.h	(revision 6809)
+++ 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 6809)
+++ 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;
@@ -50,6 +51,8 @@
 
 void XvMCOSD::CreateBuffer(XvMCContext &xvmc_ctx, int width, int height)
 {
+    VERBOSE(VB_IMPORTANT, "XvMCOSD::CreateBuffer");
+
     if (NO_SUBPICTURE == osd_subpict_mode)
     {
         VERBOSE(VB_IMPORTANT, "XvMCOSD::CreateBuffer() failed because "
@@ -131,6 +134,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 6809)
+++ libs/libmythtv/osdsurface.cpp	(working copy)
@@ -150,17 +150,50 @@
 
 OSDSurface::OSDSurface(int w, int h)
 {
+    width = w;
+    height = h;
+
+    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 * 3 / 2];
     y = yuvbuffer;
     u = yuvbuffer + w * h;
     v = u + w * h / 4;
     alpha = new unsigned char[w * h];
 
-    width = w;
-    height = h;
-
-    size = width * height;
-
     for (int i = 0; i < 256; i++)
     {
         for (int j = 0; j < 256; j++)
@@ -209,22 +242,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();
@@ -259,23 +293,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
 ///////////////////////////////////////////////////////////////////////////
@@ -383,7 +405,7 @@
 }
 #endif
 
-blendtoyv12_8_fun blendtoyv12_8_init(const OSDSurface *surface)
+blendtoyv12_8_fun blendtoyv12_8_init(const YUVSurface *surface)
 {
     (void)surface;
 #ifdef MMX
@@ -393,7 +415,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)
 {
@@ -415,7 +437,7 @@
 
 #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(YUVSurface * /*surf*/, unsigned char *src,
                                      unsigned char *usrc, unsigned char *vsrc,
                                      unsigned char *alpha, unsigned char *dest)
 {
@@ -510,7 +532,7 @@
 }
 #endif
 
-blendtoargb_8_fun blendtoargb_8_init(const OSDSurface *surface)
+blendtoargb_8_fun blendtoargb_8_init(const YUVSurface *surface)
 {
     (void)surface;
 #ifdef MMX
@@ -626,7 +648,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.
@@ -675,13 +697,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;
@@ -790,8 +812,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
@@ -801,10 +823,10 @@
  *  \param height         Number of lines in output buffer
  *  \param blend_to_black Uses Alpha to blend buffer to black
  */
-void OSDSurface::BlendToARGB(unsigned char *argbptr, uint stride, uint height,
+void YUVSurface::BlendToARGB(unsigned char *argbptr, uint stride, uint height,
                              bool blend_to_black) const
 {
-    const OSDSurface *surface = this;
+    const YUVSurface *surface = this;
     blendtoargb_8_fun blender = blendtoargb_8_init(surface);
     const unsigned char *cm = surface->cm;
 
@@ -876,8 +898,8 @@
         BlendToBlack(argbptr, stride>>2, height);
 }
 
-/** \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.
@@ -887,10 +909,10 @@
  *  \param stride Length of each line in output buffer in bytes
  *  \param height 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 height) const
 {
-    const OSDSurface *surface = this;
+    const YUVSurface *surface = this;
     int ashift = ifirst ? 0 : 4;
     int amask = ifirst ? 0x0f : 0xf0;
 
@@ -970,8 +992,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
@@ -979,14 +1001,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 height) const
 {
     DitherToI44(outbuf, false, stride, height);
 }
 
-/** \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
@@ -994,8 +1016,40 @@
  *  \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 height) const
 {
     DitherToI44(outbuf, true, stride, height);
 }
+
+
+I44Surface::I44Surface(int w, int h): OSDSurface(w,h)
+{
+printf("I44Surface - %d, %d\n",w,h);
+    i44buffer = new unsigned char [w*h];
+    Clear();
+}
+
+I44Surface::~I44Surface()
+{
+    delete [] i44buffer;
+}
+
+void I44Surface::Clear(void)
+{
+    memset(i44buffer, 0, size);
+    
+    OSDSurface::Clear();
+}
+
+void I44Surface::ClearUsed(void)
+{
+    memset(i44buffer, 0, size);
+    OSDSurface::Clear();
+}
+
+void I44Surface::BlendToI44( unsigned char *i44ptr, bool ifirst, uint stride, uint height) const
+{
+printf("BlendToI44 %d\n", size);
+    memcpy(i44ptr, i44buffer, size);//stride * XJ_height);
+}
Index: libs/libmythtv/ttfont.cpp
===================================================================
--- libs/libmythtv/ttfont.cpp	(revision 6809)
+++ 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)
 
+/*
 struct Raster_Map
 {
     int width;
@@ -44,10 +51,12 @@
     int size;
     unsigned char *bitmap;
 };
+*/
 
 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,13 @@
    rmap = new Raster_Map;
    rmap->width = (width + 3) & -4;
    rmap->rows = height;
-   rmap->cols = rmap->width;
-   rmap->size = rmap->rows * rmap->width;
+   
+   if (m_mono)
+    rmap->cols = (rmap->width+7) >> 3;
+   else
+    rmap->cols = rmap->width;
+
+   rmap->size = rmap->rows * rmap->cols;
    if (rmap->size <= 0)
    {
         delete rmap;
@@ -202,6 +219,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 +269,7 @@
            origin.x = 0;
            origin.y = 0;
 
-           FT_Glyph_To_Bitmap(&glyphs[j], ft_render_mode_normal, &origin, 1);
+           FT_Glyph_To_Bitmap(&glyphs[j], m_mono ? ft_render_mode_mono : ft_render_mode_normal, &origin, 1);
            bmap = (FT_BitmapGlyph)(glyphs[j]);
 
            glyphs_cached[j] = duplicate_raster(bmap);
@@ -311,13 +332,19 @@
        if (ymax >= rmap->rows)
            ymax = rmap->rows - 1;
 
+int x_ioff = 0, x_iread=0;
+
        if (xmin < 0)
        {
-           iread -= xmin;
+           // iread -= xmin;
+            x_iread = -xmin;
            xmin = 0;
        }
        else
-           ioff += xmin;
+        {
+            x_ioff = xmin;
+          // ioff += xmin;
+        }    
 
        if (xmax >= rmap->width)
            xmax = rmap->width - 1;
@@ -327,17 +354,83 @@
        _read = (char *)rtmp->bitmap + iread;
        _off = (char *)rmap->bitmap + ioff;
 
+//printf("rows %d ymin %d cols %d\n", rmap->rows, ymin, rmap->cols);
+
+//printf(" i %d, j '%c' xmin %d, xmax %d, x_iread %d, x_ioff %d iread %d ioff %d\n",
+//        i, j,xmin, xmax, x_iread, x_ioff, iread, ioff);
+ 
+            int len = xmax - xmin;
+            int bytes = len >> 3;
+            int rem = len & 7;
+
+            int x_read = x_iread;
+            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;
+
+//            printf(" nmask %02x, lmask %02x, bit_off %d, len %d, bytes %d, rem %d\n",
+//                    nmask, lmask, bit_off, len, bytes, rem);
+
        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;
+
+/*
+       for (x = xmin; x <= xmax; x++)
+       {
+
+        int r = x_iread + (x-xmin);
+        int w = x_ioff + (x-xmin);               
+
+        bool bit = read[r>>3] & mask[r&7];
+        
+        if (bit)
+            off[w>>3] |= mask[w&7];
+       }
+*/
+
+// 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,13 +442,101 @@
     }
 }
 
-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, * ydst, * udst, * vdst, * adst;
     uint8_t color_y = 0, color_u = 0, color_v = 0;
+    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 b,x,y;
+char ch;
+
+ asrc=rmap->bitmap;
+ adst=surface->i44buffer;
+
+ asrc += rmap->cols*offset_y+(offset_x>>3);
+ adst += xstart+ystart*surface->width;
+
+unsigned long* ldst=(unsigned long*)adst;
+
+unsigned char chmap[16];
+
+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;
+
     if (xstart < 0)
     {
         width += xstart;
@@ -411,16 +592,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 +611,7 @@
    if (w <= 0 || h <= 0)
    {
        destroy_font_raster(rtmp);
-       return;
+       return 0;
    }
    rmap = create_font_raster(w, h);
 
@@ -437,6 +619,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,37 +689,69 @@
      }
    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,
+    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,
+    if (surface->SurfaceType() == OSDSurface::SURF_YUV)
+    {
+       merge_text((YUVSurface*)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,
+       merge_text((YUVSurface*)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,
+       merge_text((YUVSurface*)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,
+       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()
 {
+    QMap<QString,Raster_Map*>::Iterator it;
+    for (it=rasters.begin(); it!= rasters.end(); ++it)
+    {
+        destroy_font_raster(*it);
+    }
+
    if (!valid)
        return;
 
@@ -526,25 +777,31 @@
 }
 
 TTFFont::TTFFont(char *file, int size, int video_width, int video_height,
-                 float hmult)
+                 float hmult, bool mono)
 {
+
    FT_Error            error;
 
    valid = false;
    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)
@@ -597,6 +854,7 @@
 
 void TTFFont::Init(void)
 {
+
    FT_Error error;
    FT_CharMap char_map;
    int xdpi = 96, ydpi = 96;
@@ -663,6 +921,7 @@
 
 void TTFFont::CalcWidth(const QString &text, int *width_return)
 {
+
    unsigned int i, pw;
 
    pw = 0;
Index: libs/libmythtv/osd.cpp
===================================================================
--- libs/libmythtv/osd.cpp	(revision 6809)
+++ libs/libmythtv/osd.cpp	(working copy)
@@ -30,6 +30,7 @@
          int dispx, int dispy, int dispw, int disph)
    : QObject()
 {
+    hasPalette=false;
     changed = false;
     vid_width = width;
     vid_height = height;
@@ -74,7 +75,15 @@
 
     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)
@@ -234,7 +243,15 @@
     }
 
     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();
 }
@@ -263,8 +280,13 @@
 TTFFont *OSD::LoadFont(QString name, int size)
 {
     QString fullname = MythContext::GetConfDir() + "/" + name;
+
+    bool mono = (surftype == "I44") ? true:false;
+
+    printf("Load font %s\n", mono?"mono":"nonmono");
+
     TTFFont *font = new TTFFont((char *)fullname.ascii(), size, vid_width,
-                                vid_height, hmult);
+                                vid_height, hmult,mono);
 
     if (font->isValid())
         return font;
@@ -273,7 +295,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;
@@ -283,7 +305,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;
     }
@@ -292,7 +314,7 @@
 
     fullname = name;
     font = new TTFFont((char *)fullname.ascii(), size, vid_width, vid_height,
-                       hmult);
+                       hmult,mono);
 
     if (font->isValid())
         return font;
@@ -316,6 +338,36 @@
     return "";
 }
 
+void OSD::parsePalette(QDomElement &element)
+{
+    int index=0;
+    hasPalette = true;
+
+    for (QDomNode child = element.firstChild(); !child.isNull(); child = child.nextSibling())
+    {
+        QDomElement node = child.toElement();
+        if (!node.isNull())
+        {
+            if (node.tagName() == "rgb")
+            {
+                int r,g,b;
+                QString text = getFirstText(node);
+
+                if (sscanf(text.data(), "%d,%d,%d", &r, &g, &b) == 3)
+                {
+                    surfPalette.append(QColor(r,g,b));
+                }
+            }
+            else
+            {
+                cerr << "Unknown tag " << node.tagName() << " in colour\n";
+                continue;
+            }
+            index ++;
+        }
+    }
+}
+
 void OSD::parseFont(QDomElement &element)
 {
     QString name;
@@ -1166,6 +1218,15 @@
             {
                 parseContainer(e);
             }
+            else if (e.tagName() == "surface")
+            {
+                surftype = getFirstText(e);
+            }
+            else if (e.tagName() == "palette")
+            {
+                parsePalette(e);
+            }
+
             else
             {
                 cerr << "Unknown element: " << e.tagName() << endl;
Index: libs/libmythtv/osdsurface.h
===================================================================
--- libs/libmythtv/osdsurface.h	(revision 6809)
+++ 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) const;
@@ -44,8 +90,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
@@ -55,12 +99,6 @@
 
     unsigned char *alpha;
 
-    int width;
-    int height;
-    int size;
-
-    QRegion usedRegions;
-
 #ifdef MMX
     short int rec_lut[256];
 #else
@@ -74,8 +112,6 @@
     blendcolor_ptr blendcolorfunc;
     blendconst_ptr blendconstfunc;
 
-    bool changed;
-
     bool usemmx;
 
     unsigned char cropTbl[256 + 2 * MAX_NEG_CROP];
@@ -85,13 +121,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;
@@ -101,7 +137,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 6809)
+++ libs/libmythtv/ttfont.h	(working copy)
@@ -12,6 +12,8 @@
 
 struct Raster_Map;
 class OSDSurface;
+class YUVSurface;
+class I44Surface;
 
 enum kTTF_Color {
     kTTF_Normal = 0, 
@@ -19,11 +21,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.
@@ -36,6 +51,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);
@@ -45,6 +61,8 @@
 
      void Reinit(int width, int height, float hmult);
 
+     static void destroy_font_raster(Raster_Map *rmap);
+
   private:
      void KillFace(void);
      void Init(void);
@@ -52,13 +70,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;
@@ -83,19 +103,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
