vdr  1.7.27
hdffosd.c
Go to the documentation of this file.
00001 /*
00002  * hdffosd.c: Implementation of the DVB HD Full Featured On Screen Display
00003  *
00004  * See the README file for copyright information and how to reach the author.
00005  *
00006  * $Id: hdffosd.c 1.12 2011/12/04 15:31:41 kls Exp $
00007  */
00008 
00009 #include "hdffosd.h"
00010 #include <linux/dvb/osd.h>
00011 #include <sys/ioctl.h>
00012 #include <sys/time.h>
00013 #include "hdffcmd.h"
00014 #include "setup.h"
00015 
00016 #define MAX_NUM_FONTFACES   8
00017 #define MAX_NUM_FONTS       8
00018 #define MAX_BITMAP_SIZE     (1024*1024)
00019 
00020 typedef struct _tFontFace
00021 {
00022     cString Name;
00023     uint32_t Handle;
00024 } tFontFace;
00025 
00026 typedef struct _tFont
00027 {
00028     uint32_t hFontFace;
00029     int Size;
00030     uint32_t Handle;
00031 } tFont;
00032 
00033 class cHdffOsd : public cOsd
00034 {
00035 private:
00036     HDFF::cHdffCmdIf * mHdffCmdIf;
00037     int mLeft;
00038     int mTop;
00039     int mDispWidth;
00040     int mDispHeight;
00041     bool shown;
00042     bool mChanged;
00043     bool mBitmapModified;
00044     uint32_t mDisplay;
00045     tFontFace mFontFaces[MAX_NUM_FONTFACES];
00046     tFont mFonts[MAX_NUM_FONTS];
00047     uint32_t mBitmapPalette;
00048     uint32_t mBitmapColors[256];
00049     uint32_t mBitmapNumColors;
00050 
00051 protected:
00052     virtual void SetActive(bool On);
00053 public:
00054     cHdffOsd(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level);
00055     virtual ~cHdffOsd();
00056     cBitmap *GetBitmap(int Area);
00057     virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
00058     virtual eOsdError SetAreas(const tArea *Areas, int NumAreas);
00059     virtual void SaveRegion(int x1, int y1, int x2, int y2);
00060     virtual void RestoreRegion(void);
00061     virtual void DrawPixel(int x, int y, tColor Color);
00062     virtual void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool ReplacePalette = false, bool Overlay = false);
00063     virtual void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault);
00064     virtual void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color);
00065     virtual void DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants = 0);
00066     virtual void DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type);
00067     virtual void Flush(void);
00068 };
00069 
00070 cHdffOsd::cHdffOsd(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level)
00071 :   cOsd(Left, Top, Level)
00072 {
00073     double pixelAspect;
00074     HdffOsdConfig_t config;
00075 
00076     //printf("cHdffOsd %d, %d, %d\n", Left, Top, Level);
00077     mHdffCmdIf = pHdffCmdIf;
00078     mLeft = Left;
00079     mTop = Top;
00080     shown = false;
00081     mChanged = false;
00082     mBitmapModified = false;
00083     mBitmapPalette = HDFF_INVALID_HANDLE;
00084     config.FontKerning = false;
00085     config.FontAntialiasing = Setup.AntiAlias ? true : false;
00086     mHdffCmdIf->CmdOsdConfigure(&config);
00087 
00088     gHdffSetup.GetOsdSize(mDispWidth, mDispHeight, pixelAspect);
00089     mDisplay = mHdffCmdIf->CmdOsdCreateDisplay(mDispWidth, mDispHeight, HDFF_COLOR_TYPE_ARGB8888);
00090     mHdffCmdIf->CmdOsdSetDisplayOutputRectangle(mDisplay, 0, 0, HDFF_SIZE_FULL_SCREEN, HDFF_SIZE_FULL_SCREEN);
00091     for (int i = 0; i < MAX_NUM_FONTFACES; i++)
00092     {
00093         mFontFaces[i].Name = "";
00094         mFontFaces[i].Handle = HDFF_INVALID_HANDLE;
00095     }
00096     for (int i = 0; i < MAX_NUM_FONTS; i++)
00097     {
00098         mFonts[i].hFontFace = HDFF_INVALID_HANDLE;
00099         mFonts[i].Size = 0;
00100         mFonts[i].Handle = HDFF_INVALID_HANDLE;
00101     }
00102 }
00103 
00104 cHdffOsd::~cHdffOsd()
00105 {
00106     //printf("~cHdffOsd %d %d\n", mLeft, mTop);
00107     SetActive(false);
00108 
00109     for (int i = 0; i < MAX_NUM_FONTS; i++)
00110     {
00111         if (mFonts[i].Handle == HDFF_INVALID_HANDLE)
00112             break;
00113         mHdffCmdIf->CmdOsdDeleteFont(mFonts[i].Handle);
00114     }
00115     for (int i = 0; i < MAX_NUM_FONTFACES; i++)
00116     {
00117         if (mFontFaces[i].Handle == HDFF_INVALID_HANDLE)
00118             break;
00119         mHdffCmdIf->CmdOsdDeleteFontFace(mFontFaces[i].Handle);
00120     }
00121 
00122     if (mBitmapPalette != HDFF_INVALID_HANDLE)
00123         mHdffCmdIf->CmdOsdDeletePalette(mBitmapPalette);
00124     mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0);
00125     mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
00126     mHdffCmdIf->CmdOsdDeleteDisplay(mDisplay);
00127 }
00128 
00129 cBitmap * cHdffOsd::GetBitmap(int Area)
00130 {
00131     //printf("GetBitmap %d\n", Area);
00132     mChanged = true;
00133     mBitmapModified = true;
00134     return cOsd::GetBitmap(Area);
00135 }
00136 
00137 eOsdError cHdffOsd::CanHandleAreas(const tArea *Areas, int NumAreas)
00138 {
00139     eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas);
00140     if (Result == oeOk)
00141     {
00142         for (int i = 0; i < NumAreas; i++)
00143         {
00144             if (Areas[i].bpp != 1 && Areas[i].bpp != 2 && Areas[i].bpp != 4 && Areas[i].bpp != 8)
00145                 return oeBppNotSupported;
00146         }
00147     }
00148     return Result;
00149 }
00150 
00151 eOsdError cHdffOsd::SetAreas(const tArea *Areas, int NumAreas)
00152 {
00153     for (int i = 0; i < NumAreas; i++)
00154     {
00155         //printf("SetAreas %d: %d %d %d %d %d\n", i, Areas[i].x1, Areas[i].y1, Areas[i].x2, Areas[i].y2, Areas[i].bpp);
00156     }
00157     if (shown)
00158     {
00159         mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0);
00160         mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
00161         shown = false;
00162     }
00163     return cOsd::SetAreas(Areas, NumAreas);
00164 }
00165 
00166 void cHdffOsd::SetActive(bool On)
00167 {
00168     if (On != Active())
00169     {
00170         cOsd::SetActive(On);
00171         if (On)
00172         {
00173             if (GetBitmap(0)) // only flush here if there are already bitmaps
00174                 Flush();
00175         }
00176         else if (shown)
00177         {
00178             mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0);
00179             mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
00180             shown = false;
00181         }
00182     }
00183 }
00184 
00185 void cHdffOsd::SaveRegion(int x1, int y1, int x2, int y2)
00186 {
00187     mHdffCmdIf->CmdOsdSaveRegion(mDisplay, mLeft + x1, mTop + y1, x2 - x1 + 1, y2 - y1 + 1);
00188     mChanged = true;
00189     mBitmapModified = false;
00190 }
00191 
00192 void cHdffOsd::RestoreRegion(void)
00193 {
00194     mHdffCmdIf->CmdOsdRestoreRegion(mDisplay);
00195     mChanged = true;
00196     mBitmapModified = false;
00197 }
00198 
00199 void cHdffOsd::DrawPixel(int x, int y, tColor Color)
00200 {
00201     //printf("DrawPixel\n");
00202     mBitmapModified = false;
00203 }
00204 
00205 void cHdffOsd::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool ReplacePalette, bool Overlay)
00206 {
00207     //printf("DrawBitmap %d %d %d\n", x, y, Overlay);
00208     int i;
00209     int numColors;
00210     const tColor * colors = Bitmap.Colors(numColors);
00211 
00212     for (i = 0; i < numColors; i++)
00213     {
00214         mBitmapColors[i] = colors[i];
00215         if (ColorFg || ColorBg)
00216         {
00217             if (i == 0)
00218                 mBitmapColors[i] = ColorBg;
00219             else if (i == 1)
00220                 mBitmapColors[i] = ColorFg;
00221         }
00222     }
00223     if (mBitmapPalette == HDFF_INVALID_HANDLE)
00224     {
00225         mBitmapPalette = mHdffCmdIf->CmdOsdCreatePalette(HDFF_COLOR_TYPE_CLUT8,
00226                 HDFF_COLOR_FORMAT_ARGB, numColors, mBitmapColors);
00227     }
00228     else
00229     {
00230         mHdffCmdIf->CmdOsdSetPaletteColors(mBitmapPalette,
00231                 HDFF_COLOR_FORMAT_ARGB, 0, numColors, mBitmapColors);
00232     }
00233     mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, mLeft + x, mTop + y,
00234         (uint8_t *) Bitmap.Data(0, 0), Bitmap.Width(), Bitmap.Height(),
00235         Bitmap.Width() * Bitmap.Height(), HDFF_COLOR_TYPE_CLUT8, mBitmapPalette);
00236 #if 0
00237     uint32_t * tmpBitmap = new uint32_t[Bitmap.Width() * Bitmap.Height()];
00238     for (int ix = 0; ix < Bitmap.Width(); ix++)
00239     {
00240         for (int iy = 0; iy < Bitmap.Height(); iy++)
00241         {
00242             const tIndex * pixel = Bitmap.Data(ix, iy);
00243             tColor color = Bitmap.Color(*pixel);
00244             if (!Overlay || *pixel != 0)
00245             {
00246                 if (ColorFg || ColorBg)
00247                 {
00248                     if (*pixel == 0)
00249                         color = ColorBg;
00250                     else if (*pixel == 1)
00251                         color = ColorFg;
00252                 }
00253                 tmpBitmap[Bitmap.Width() * iy + ix] = color;
00254             }
00255         }
00256     }
00257     mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, mLeft + x, mTop + y,
00258         (uint8_t *) tmpBitmap, Bitmap.Width(), Bitmap.Height(),
00259         Bitmap.Width() * Bitmap.Height() * 4, HDFF::colorTypeARGB8888, InvalidHandle);
00260     delete[] tmpBitmap;
00261 #endif
00262     mChanged = true;
00263     mBitmapModified = false;
00264 }
00265 
00266 void cHdffOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width, int Height, int Alignment)
00267 {
00268     int w = Font->Width(s);
00269     int h = Font->Height();
00270     int limit = 0;
00271     int cw = Width ? Width : w;
00272     int ch = Height ? Height : h;
00273     int i;
00274     int size = Font->Size();
00275     tFontFace * pFontFace;
00276     tFont * pFont;
00277 
00278     if (ColorBg != clrTransparent)
00279         mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, mLeft + x, mTop + y, cw, ch, ColorBg);
00280 
00281     if (s == NULL)
00282         return;
00283 
00284     pFontFace = NULL;
00285     for (i = 0; i < MAX_NUM_FONTFACES; i++)
00286     {
00287         if (mFontFaces[i].Handle == HDFF_INVALID_HANDLE)
00288             break;
00289 
00290         if (strcmp(mFontFaces[i].Name, Font->FontName()) == 0)
00291         {
00292             pFontFace = &mFontFaces[i];
00293             break;
00294         }
00295     }
00296     if (pFontFace == NULL)
00297     {
00298         if (i < MAX_NUM_FONTFACES)
00299         {
00300             cString fontFileName = Font->FontName();
00301             FILE * fp = fopen(fontFileName, "rb");
00302             if (fp)
00303             {
00304                 fseek(fp, 0, SEEK_END);
00305                 long fileSize = ftell(fp);
00306                 fseek(fp, 0, SEEK_SET);
00307                 if (fileSize > 0)
00308                 {
00309                     uint8_t * buffer = new uint8_t[fileSize];
00310                     if (buffer)
00311                     {
00312                         if (fread(buffer, fileSize, 1, fp) == 1)
00313                         {
00314                             mFontFaces[i].Handle = mHdffCmdIf->CmdOsdCreateFontFace(buffer, fileSize);
00315                             if (mFontFaces[i].Handle != HDFF_INVALID_HANDLE)
00316                             {
00317                                 mFontFaces[i].Name = Font->FontName();
00318                                 pFontFace = &mFontFaces[i];
00319                             }
00320                         }
00321                         delete[] buffer;
00322                     }
00323                 }
00324                 fclose(fp);
00325             }
00326         }
00327     }
00328     if (pFontFace == NULL)
00329         return;
00330 
00331     pFont = NULL;
00332     for (i = 0; i < MAX_NUM_FONTS; i++)
00333     {
00334         if (mFonts[i].Handle == HDFF_INVALID_HANDLE)
00335             break;
00336 
00337         if (mFonts[i].hFontFace == pFontFace->Handle
00338           && mFonts[i].Size == size)
00339         {
00340             pFont = &mFonts[i];
00341             break;
00342         }
00343     }
00344     if (pFont == NULL)
00345     {
00346         if (i < MAX_NUM_FONTS)
00347         {
00348             mFonts[i].Handle = mHdffCmdIf->CmdOsdCreateFont(pFontFace->Handle, size);
00349             if (mFonts[i].Handle != HDFF_INVALID_HANDLE)
00350             {
00351                 mFonts[i].hFontFace = pFontFace->Handle;
00352                 mFonts[i].Size = size;
00353                 pFont = &mFonts[i];
00354             }
00355         }
00356     }
00357     if (pFont == NULL)
00358         return;
00359 
00360     mHdffCmdIf->CmdOsdSetDisplayClippingArea(mDisplay, true, mLeft + x, mTop + y, cw, ch);
00361 
00362     if (Width || Height)
00363     {
00364         limit = x + cw;// - mLeft;
00365         if (Width)
00366         {
00367             if ((Alignment & taLeft) != 0)
00368                 ;
00369             else if ((Alignment & taRight) != 0)
00370             {
00371                 if (w < Width)
00372                     x += Width - w;
00373             }
00374             else
00375             { // taCentered
00376                 if (w < Width)
00377                     x += (Width - w) / 2;
00378             }
00379         }
00380         if (Height)
00381         {
00382             if ((Alignment & taTop) != 0)
00383                 ;
00384             else if ((Alignment & taBottom) != 0)
00385             {
00386                 if (h < Height)
00387                     y += Height - h;
00388             }
00389             else
00390             { // taCentered
00391                 if (h < Height)
00392                     y += (Height - h) / 2;
00393             }
00394         }
00395     }
00396     //x -= mLeft;
00397     //y -= mTop;
00398     {
00399         uint16_t tmp[1000];
00400         uint16_t len = 0;
00401         while (*s && (len < (sizeof(tmp) - 1)))
00402         {
00403             int sl = Utf8CharLen(s);
00404             uint sym = Utf8CharGet(s, sl);
00405             s += sl;
00406             tmp[len] = sym;
00407             len++;
00408         }
00409         tmp[len] = 0;
00410         mHdffCmdIf->CmdOsdDrawTextW(mDisplay, pFont->Handle, x + mLeft, y + mTop + h, tmp, ColorFg);
00411     }
00412     //mHdffCmdIf->CmdOsdDrawText(mDisplay, pFont->Handle, x + mLeft, y + mTop + h - 7, s, ColorFg);
00413     mHdffCmdIf->CmdOsdSetDisplayClippingArea(mDisplay, false, 0, 0, 0, 0);
00414     //Font->DrawText(this, x, y, s, ColorFg, ColorBg, limit);
00415     mChanged = true;
00416     mBitmapModified = false;
00417 }
00418 
00419 void cHdffOsd::DrawRectangle(int x1, int y1, int x2, int y2, tColor Color)
00420 {
00421     mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, mLeft + x1, mTop + y1, x2 - x1 + 1, y2 - y1 + 1, Color);
00422     mChanged = true;
00423     mBitmapModified = false;
00424 }
00425 
00426 void cHdffOsd::DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants)
00427 {
00428     uint32_t flags;
00429     int cx;
00430     int cy;
00431     int rx;
00432     int ry;
00433 
00434     switch (abs(Quadrants))
00435     {
00436         case 1:
00437             if (Quadrants > 0)
00438                 flags = HDFF_DRAW_QUARTER_TOP_RIGHT;
00439             else
00440                 flags = HDFF_DRAW_QUARTER_TOP_RIGHT_INVERTED;
00441             cx = x1;
00442             cy = y2;
00443             rx = x2 - x1;
00444             ry = y2 - y1;
00445             break;
00446         case 2:
00447             if (Quadrants > 0)
00448                 flags = HDFF_DRAW_QUARTER_TOP_LEFT;
00449             else
00450                 flags = HDFF_DRAW_QUARTER_TOP_LEFT_INVERTED;
00451             cx = x2;
00452             cy = y2;
00453             rx = x2 - x1;
00454             ry = y2 - y1;
00455             break;
00456         case 3:
00457             if (Quadrants > 0)
00458                 flags = HDFF_DRAW_QUARTER_BOTTOM_LEFT;
00459             else
00460                 flags = HDFF_DRAW_QUARTER_BOTTOM_LEFT_INVERTED;
00461             cx = x2;
00462             cy = y1;
00463             rx = x2 - x1;
00464             ry = y2 - y1;
00465             break;
00466         case 4:
00467             if (Quadrants > 0)
00468                 flags = HDFF_DRAW_QUARTER_BOTTOM_RIGHT;
00469             else
00470                 flags = HDFF_DRAW_QUARTER_BOTTOM_RIGHT_INVERTED;
00471             cx = x1;
00472             cy = y1;
00473             rx = x2 - x1;
00474             ry = y2 - y1;
00475             break;
00476         case 5:
00477             flags = HDFF_DRAW_HALF_RIGHT;
00478             cx = x1;
00479             cy = (y1 + y2) / 2;
00480             rx = x2 - x1;
00481             ry = (y2 - y1) / 2;
00482             break;
00483         case 6:
00484             flags = HDFF_DRAW_HALF_TOP;
00485             cx = (x1 + x2) / 2;
00486             cy = y2;
00487             rx = (x2 - x1) / 2;
00488             ry = y2 - y1;
00489             break;
00490         case 7:
00491             flags = HDFF_DRAW_HALF_LEFT;
00492             cx = x2;
00493             cy = (y1 + y2) / 2;
00494             rx = x2 - x1;
00495             ry = (y2 - y1) / 2;
00496             break;
00497         case 8:
00498             flags = HDFF_DRAW_HALF_BOTTOM;
00499             cx = (x1 + x2) / 2;
00500             cy = y1;
00501             rx = (x2 - x1) / 2;
00502             ry = y2 - y1;
00503             break;
00504         default:
00505             flags = HDFF_DRAW_FULL;
00506             cx = (x1 + x2) / 2;
00507             cy = (y1 + y2) / 2;
00508             rx = (x2 - x1) / 2;
00509             ry = (y2 - y1) / 2;
00510             break;
00511     }
00512     mHdffCmdIf->CmdOsdDrawEllipse(mDisplay, mLeft + cx, mTop + cy, rx, ry, Color, flags);
00513     mChanged = true;
00514     mBitmapModified = false;
00515 }
00516 
00517 void cHdffOsd::DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type)
00518 {
00519     //printf("DrawSlope\n");
00520     mChanged = true;
00521     mBitmapModified = false;
00522 }
00523 
00524 void cHdffOsd::Flush(void)
00525 {
00526     if (!Active())
00527         return;
00528 
00529     if (!mChanged)
00530         return;
00531 
00532     //printf("Flush\n");
00533     if (mBitmapModified)
00534     {
00535         cBitmap *Bitmap;
00536         for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++)
00537         {
00538             DrawBitmap(0, 0, *Bitmap);
00539         }
00540     }
00541 
00542     mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
00543 
00544     mChanged = false;
00545     mBitmapModified = false;
00546 }
00547 
00548 
00549 class cHdffOsdRaw : public cOsd
00550 {
00551 private:
00552     HDFF::cHdffCmdIf * mHdffCmdIf;
00553     int mDispWidth;
00554     int mDispHeight;
00555     bool refresh;
00556     uint32_t mDisplay;
00557     uint32_t mBitmapPalette;
00558     uint32_t mBitmapColors[256];
00559     uint32_t mBitmapNumColors;
00560 
00561 protected:
00562     virtual void SetActive(bool On);
00563 public:
00564     cHdffOsdRaw(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level);
00565     virtual ~cHdffOsdRaw();
00566     virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
00567     virtual eOsdError SetAreas(const tArea *Areas, int NumAreas);
00568     virtual void Flush(void);
00569 };
00570 
00571 cHdffOsdRaw::cHdffOsdRaw(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level)
00572 :   cOsd(Left, Top, Level)
00573 {
00574     double pixelAspect;
00575 
00576     //printf("cHdffOsdRaw %d, %d, %d\n", Left, Top, Level);
00577     mHdffCmdIf = pHdffCmdIf;
00578     refresh = true;
00579     mBitmapPalette = HDFF_INVALID_HANDLE;
00580     mDisplay = HDFF_INVALID_HANDLE;
00581 
00582     gHdffSetup.GetOsdSize(mDispWidth, mDispHeight, pixelAspect);
00583 }
00584 
00585 cHdffOsdRaw::~cHdffOsdRaw()
00586 {
00587     //printf("~cHdffOsdRaw %d %d\n", Left(), Top());
00588     if (mDisplay != HDFF_INVALID_HANDLE)
00589     {
00590         mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0);
00591         mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
00592     }
00593     if (mBitmapPalette != HDFF_INVALID_HANDLE)
00594         mHdffCmdIf->CmdOsdDeletePalette(mBitmapPalette);
00595     mBitmapPalette = HDFF_INVALID_HANDLE;
00596     if (mDisplay != HDFF_INVALID_HANDLE)
00597        mHdffCmdIf->CmdOsdDeleteDisplay(mDisplay);
00598     mDisplay = HDFF_INVALID_HANDLE;
00599 }
00600 
00601 void cHdffOsdRaw::SetActive(bool On)
00602 {
00603     if (On != Active())
00604     {
00605         cOsd::SetActive(On);
00606         if (On)
00607         {
00608             if (mDisplay == HDFF_INVALID_HANDLE)
00609             {
00610                 mDisplay = mHdffCmdIf->CmdOsdCreateDisplay(mDispWidth, mDispHeight, HDFF_COLOR_TYPE_ARGB8888);
00611                 if (mDisplay != HDFF_INVALID_HANDLE)
00612                     mHdffCmdIf->CmdOsdSetDisplayOutputRectangle(mDisplay, 0, 0, HDFF_SIZE_FULL_SCREEN, HDFF_SIZE_FULL_SCREEN);
00613             }
00614             refresh = true;
00615             if (GetBitmap(0)) // only flush here if there are already bitmaps
00616                 Flush();
00617         }
00618         else
00619         {
00620             if (mDisplay != HDFF_INVALID_HANDLE)
00621             {
00622                 mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0);
00623                 mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
00624             }
00625             if (mBitmapPalette != HDFF_INVALID_HANDLE)
00626                 mHdffCmdIf->CmdOsdDeletePalette(mBitmapPalette);
00627             mBitmapPalette = HDFF_INVALID_HANDLE;
00628             if (mDisplay != HDFF_INVALID_HANDLE)
00629                 mHdffCmdIf->CmdOsdDeleteDisplay(mDisplay);
00630             mDisplay = HDFF_INVALID_HANDLE;
00631         }
00632     }
00633 }
00634 
00635 eOsdError cHdffOsdRaw::CanHandleAreas(const tArea *Areas, int NumAreas)
00636 {
00637     eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas);
00638     if (Result == oeOk)
00639     {
00640         for (int i = 0; i < NumAreas; i++)
00641         {
00642             if (Areas[i].bpp != 1 && Areas[i].bpp != 2 && Areas[i].bpp != 4 && Areas[i].bpp != 8
00643                 && (Areas[i].bpp != 32 || !gHdffSetup.TrueColorOsd))
00644                 return oeBppNotSupported;
00645         }
00646     }
00647     return Result;
00648 }
00649 
00650 eOsdError cHdffOsdRaw::SetAreas(const tArea *Areas, int NumAreas)
00651 {
00652     for (int i = 0; i < NumAreas; i++)
00653     {
00654         //printf("SetAreas %d: %d %d %d %d %d\n", i, Areas[i].x1, Areas[i].y1, Areas[i].x2, Areas[i].y2, Areas[i].bpp);
00655     }
00656     if (mDisplay != HDFF_INVALID_HANDLE)
00657     {
00658         mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0);
00659         mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
00660         refresh = true;
00661     }
00662     return cOsd::SetAreas(Areas, NumAreas);
00663 }
00664 
00665 void cHdffOsdRaw::Flush(void)
00666 {
00667     if (!Active() || (mDisplay == HDFF_INVALID_HANDLE))
00668         return;
00669     //struct timeval start;
00670     //struct timeval end;
00671     //struct timezone timeZone;
00672     //gettimeofday(&start, &timeZone);
00673 
00674     bool render = false;
00675     if (IsTrueColor())
00676     {
00677         LOCK_PIXMAPS;
00678         while (cPixmapMemory *pm = RenderPixmaps())
00679         {
00680             int w = pm->ViewPort().Width();
00681             int h = pm->ViewPort().Height();
00682             int d = w * sizeof(tColor);
00683             int Chunk = MAX_BITMAP_SIZE / w / sizeof(tColor);
00684             if (Chunk > h)
00685                 Chunk = h;
00686             for (int y = 0; y < h; y += Chunk)
00687             {
00688                  int hc = Chunk;
00689                  if (y + hc > h)
00690                      hc = h - y;
00691                  mHdffCmdIf->CmdOsdDrawBitmap(mDisplay,
00692                      Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y() + y,
00693                      pm->Data() + y * d, w, hc, hc * d,
00694                      HDFF_COLOR_TYPE_ARGB8888, HDFF_INVALID_HANDLE);
00695             }
00696             delete pm;
00697             render = true;
00698         }
00699     }
00700     else
00701     {
00702         uint8_t * buffer = new uint8_t[MAX_BITMAP_SIZE];
00703         if (!buffer)
00704             return;
00705         cBitmap * bitmap;
00706         for (int i = 0; (bitmap = GetBitmap(i)) != NULL; i++)
00707         {
00708             int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
00709             if (refresh || bitmap->Dirty(x1, y1, x2, y2))
00710             {
00711                 if (refresh)
00712                 {
00713                     x2 = bitmap->Width() - 1;
00714                     y2 = bitmap->Height() - 1;
00715                 }
00716                 // commit colors:
00717                 int numColors;
00718                 const tColor * colors = bitmap->Colors(numColors);
00719                 if (colors)
00720                 {
00721                     for (int c = 0; c < numColors; c++)
00722                         mBitmapColors[c] = colors[c];
00723                     if (mBitmapPalette == HDFF_INVALID_HANDLE)
00724                     {
00725                         mBitmapPalette = mHdffCmdIf->CmdOsdCreatePalette(HDFF_COLOR_TYPE_CLUT8,
00726                             HDFF_COLOR_FORMAT_ARGB, numColors, mBitmapColors);
00727                     }
00728                     else
00729                     {
00730                         mHdffCmdIf->CmdOsdSetPaletteColors(mBitmapPalette,
00731                             HDFF_COLOR_FORMAT_ARGB, 0, numColors, mBitmapColors);
00732                     }
00733                 }
00734                 // commit modified data:
00735                 int width = x2 - x1 + 1;
00736                 int height = y2 - y1 + 1;
00737                 int chunk = MAX_BITMAP_SIZE / width;
00738                 if (chunk > height)
00739                     chunk = height;
00740                 for (int y = 0; y < height; y += chunk)
00741                 {
00742                     int hc = chunk;
00743                     if (y + hc > height)
00744                         hc = height - y;
00745                     for (int r = 0; r < hc; r++)
00746                         memcpy(buffer + r * width, bitmap->Data(x1, y1 + y + r), width);
00747                     mHdffCmdIf->CmdOsdDrawBitmap(mDisplay,
00748                         Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1 + y,
00749                         buffer, width, hc, hc * width,
00750                         HDFF_COLOR_TYPE_CLUT8, mBitmapPalette);
00751                 }
00752                 render = true;
00753             }
00754             bitmap->Clean();
00755         }
00756         delete[] buffer;
00757     }
00758     if (render)
00759     {
00760         mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
00761         //gettimeofday(&end, &timeZone);
00762         //int timeNeeded = end.tv_usec - start.tv_usec;
00763         //timeNeeded += (end.tv_sec - start.tv_sec) * 1000000;
00764         //printf("time = %d\n", timeNeeded);
00765     }
00766     refresh = false;
00767 }
00768 
00769 
00770 
00771 
00772 cHdffOsdProvider::cHdffOsdProvider(HDFF::cHdffCmdIf * HdffCmdIf)
00773 {
00774     mHdffCmdIf = HdffCmdIf;
00775 }
00776 
00777 cOsd *cHdffOsdProvider::CreateOsd(int Left, int Top, uint Level)
00778 {
00779     //printf("CreateOsd %d %d %d\n", Left, Top, Level);
00780     if (gHdffSetup.HighLevelOsd)
00781         return new cHdffOsd(Left, Top, mHdffCmdIf, Level);
00782     else
00783         return new cHdffOsdRaw(Left, Top, mHdffCmdIf, Level);
00784 }
00785 
00786 bool cHdffOsdProvider::ProvidesTrueColor(void)
00787 {
00788     return gHdffSetup.TrueColorOsd && !gHdffSetup.HighLevelOsd;
00789 }