/*
 *  MediaMVP Output Device for VDR
 *
 *  $Id: mvposd.c,v 1.4 2004/05/27 19:05:44 dom Exp $ 
 *  $Date: 2004/05/27 19:05:44 $
 *
 *  This does the OSD
 *
 */


#include "mvpprog.h"

#if VDRVERSNUM >= 10307
cMvpOsd::cMvpOsd(int Left, int Top, surface_t *surface, cMvpProgram *prog)
    :cOsd(Left, Top) 
{
    sfc = surface;
    program = prog;

}
cMvpOsd::~cMvpOsd()
{
    program->SendEvent(MEVT_MENU_OFF);
    surface_clear(sfc,0);
}

/* We can handle any number of windows - haha */
eOsdError cMvpOsd::CanHandleAreas(const tArea *Areas, int NumAreas)
{
    eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas);

    return Result;
}

void cMvpOsd::Flush(void)
{
    cBitmap *Bitmap;
    tColor   tot = 0;
    bool     upd = false;

    for ( int i = 0; ( Bitmap = GetBitmap(i)) != NULL; i++ ) {
        int  x1 = 0, y1 = 0, x2 = 0, y2 = 0;
        if ( Bitmap->Dirty(x1,y2,x2,y2) ) {
            upd = true;
            for ( int yp = y1; yp <= y2; yp++ ) {
                for ( int xp = x1; xp <= x2; xp++  ) {
                    tColor c = Bitmap->Color(*Bitmap->Data(xp,yp));
                    if ( tot == 0 && c )
                        tot |= c;

                    surface_set_pixel(sfc,xp +  Bitmap->X0() + Left(),yp + Top() + Bitmap->Y0(), c );                       
                }
            }
        }
    }
    if ( tot )
        program->SendEvent(MEVT_MENU_ON);
    else {
        surface_clear(sfc,0x00000000);
        program->SendEvent(MEVT_UPDATE);
        program->SendEvent(MEVT_MENU_OFF);
    }

    if ( upd == true )
        program->SendEvent(MEVT_UPDATE);
}

void cMvpOsd::Hide(cBitmap *Bitmap)
{
    for ( int yp = 0; yp < Bitmap->Height(); yp++ ) {
        for ( int xp = 0; xp < Bitmap->Width(); xp++ ) {
            surface_set_pixel(sfc,xp +  Bitmap->X0() + Left(),yp + Top() + Bitmap->Y0(), 0 );                       
        }
    }

    program->SendEvent(MEVT_UPDATE);
}


// --- cDvbOsdProvider -------------------------------------------------------

cMvpOsdProvider::cMvpOsdProvider(surface_t *surface, cMvpProgram *prog)
{
    sfc = surface;
    program = prog;
}

cOsd *cMvpOsdProvider::CreateOsd(int Left, int Top )
{
  return new cMvpOsd(Left, Top, sfc, program);
}





#else
cMvpOsd::cMvpOsd(cMvpProgram *prog,surface_t *surface, int X, int Y)
    :cOsdBase(X, Y) 
{
    memset(m_ShownWindows, 0, sizeof(m_ShownWindows));
    program = prog;
    sfc = surface;
}

cMvpOsd::~cMvpOsd()
{  
    program->SendEvent(MEVT_MENU_OFF);
    surface_clear(sfc,0);
    for (int i = 0; i < NumWindows(); i++)
         CloseWindow(GetWindowNr(i));
}

bool cMvpOsd::OpenWindow(cWindow *Window)
{
    m_ShownWindows[Window->Handle()] = true;
    if (Window->ClearWithBackground()) {
        for ( int yp = 0; yp < Window->Height(); yp++ ) {
            for ( int xp = 0; xp < Window->Width(); xp++ ) {
                eDvbColor c = clrBackground;
                surface_set_pixel(sfc,xp +  Window->X0() + X0(),yp + Y0() + Window->Y0(), ( (c & 0xFF) << 16 ) | ( c & 0x0000FF00 ) | (( c & 0x00FF0000) >> 16 ) );              
            }
        } 
        program->SendEvent(MEVT_MENU_ON);
        program->SendEvent(MEVT_UPDATE);   
    }

    return true;
}

void cMvpOsd::CommitWindow(cWindow *Window)
{
    int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
     
    if ( Window == NULL ) 
           return;

    if (!m_ShownWindows[Window->Handle()])
        return;


    if (Window->Dirty(x1, y1, x2, y2)) {

        for ( int yp = y1; yp <= y2; yp++ ) {
            for ( int xp = x1; xp <= x2; xp++  ) {
                eDvbColor c = Window->GetColor(*Window->Data(xp,yp));
                surface_set_pixel(sfc,xp +  Window->X0() + X0(),yp + Y0() + Window->Y0(),( (c & 0xFF) << 16 ) | ( c & 0x0000FF00 ) | (( c & 0x00FF0000) >> 16 ));
            }
        }
        program->SendEvent(MEVT_UPDATE);
    }

}

void cMvpOsd::ShowWindow(cWindow *Window)
{
    for ( int yp = 0; yp < Window->Height(); yp++ ) {
        for ( int xp = 0; xp < Window->Width(); xp++ ) {
            eDvbColor c = Window->GetColor(*Window->Data(xp,yp));
            surface_set_pixel(sfc,xp +  Window->X0() + X0(),yp + Y0() + Window->Y0(),( (c & 0xFF) << 16 ) | ( c & 0x0000FF00 ) | (( c & 0x00FF0000) >> 16 ));

        }
    }  
    program->SendEvent(MEVT_UPDATE);
}

void cMvpOsd::HideWindow(cWindow *Window, bool Hide)
{ 
    m_ShownWindows[Window->Handle()] = !Hide;

    if ( Hide ) {
        for ( int yp = 0; yp < Window->Height(); yp++ ) {
            for ( int xp = 0; xp < Window->Width(); xp++ ) {
                uint32_t c = 0;
                surface_set_pixel(sfc,xp +  Window->X0() + X0(),yp + Y0() + Window->Y0(),(uint32_t )c);
            }
        } 
    }   
    program->SendEvent(MEVT_UPDATE);
}



void cMvpOsd::CloseWindow(cWindow *Window)
{
    HideWindow(Window, true);
    m_ShownWindows[Window->Handle()] = false;  
}

void cMvpOsd::MoveWindow(cWindow *Window, int X, int Y)
{    
    CloseWindow(Window);
    m_ShownWindows[Window->Handle()] = true;
    for ( int yp = 0; yp < Window->Height(); yp++ ) {
        for ( int xp = 0; xp < Window->Width(); xp++ ) {
            eDvbColor c = Window->GetColor(*Window->Data(xp,yp));
            surface_set_pixel(sfc,xp +  Window->X0() + X0(),yp + Y0() + Window->Y0(),( (c & 0xFF) << 16 ) | ( c & 0x0000FF00 ) | (( c & 0x00FF0000) >> 16 ));
        }
    }  
    program->SendEvent(MEVT_UPDATE);
}
#endif
