Home

Dokumentation

Impressum

Dokumentation VDR
 

Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

osdbase.c

Go to the documentation of this file.
00001 
00010 #include "osdbase.h"
00011 #include <signal.h>
00012 #include <stdlib.h>
00013 #include <sys/ioctl.h>
00014 #include <sys/stat.h>
00015 #include <sys/unistd.h>
00016 #include "tools.h"
00017 
00022 cPalette::cPalette(int Bpp)
00023 {
00024   maxColors = 1 << Bpp;
00025   numColors = 0;
00026   full = false;
00027 }
00028 
00029 void cPalette::SetColor(int Index, eDvbColor Color)
00030 {
00031   if (Index < maxColors) {
00032      if (numColors < Index)
00033         numColors = Index + 1;
00034      used[Index] = true;
00035      color[Index] = Color;
00036      fetched[Index] = false;
00037      }
00038 }
00039 
00040 int cPalette::Index(eDvbColor Color)
00041 {
00042 #if __BYTE_ORDER == __BIG_ENDIAN
00043   Color = eDvbColor(((Color & 0xFF) << 24) | ((Color & 0xFF00) << 8) | ((Color & 0xFF0000) >> 8) | ((Color & 0xFF000000) >> 24));
00044 #endif
00045   for (int i = 0; i < numColors; i++) {
00046       if (color[i] == Color) {
00047          used[i] = true;
00048          return i;
00049          }
00050       }
00051   if (!full) {
00052      if (numColors < maxColors) {
00053         color[numColors++] = Color;
00054         used[numColors - 1] = true;
00055         fetched[numColors - 1] = false;
00056         return numColors - 1;
00057         }
00058      for (int i = maxColors; --i >= 0; ) {
00059          if (!used[i]) {
00060             color[i] = Color;
00061             used[i] = true;
00062             fetched[i] = false;
00063             return i;
00064             }
00065          }
00066      esyslog("ERROR: too many different colors used in palette");
00067      full = true;
00068      }
00069   return 0;
00070 }
00071 
00072 void cPalette::Reset(void)
00073 {
00074   for (int i = 0; i < numColors; i++)
00075       used[i] = false;
00076   full = false;
00077 }
00078 
00079 const eDvbColor *cPalette::NewColors(int &FirstColor, int &LastColor)
00080 {
00081   for (FirstColor = 0; FirstColor < numColors; FirstColor++) {
00082       if (!fetched[FirstColor]) {
00083          for (LastColor = FirstColor; LastColor < numColors && !fetched[LastColor]; LastColor++)
00084              fetched[LastColor] = true;
00085          LastColor--; // the loop ended one past the last one!
00086          return &color[FirstColor];
00087          }
00088       }
00089   return NULL;
00090 }
00091 
00092 const eDvbColor *cPalette::AllColors(int &NumColors)
00093 {
00094   NumColors = numColors;
00095   return numColors ? color : NULL;
00096 }
00097 
00098 void cPalette::Take(const cPalette &Palette, tIndexes *Indexes)
00099 {
00100   for (int i = 0; i < Palette.numColors; i++) {
00101       if (Palette.used[i]) {
00102          int n = Index(Palette.color[i]);
00103          if (Indexes)
00104             (*Indexes)[i] = n;
00105          }
00106       }
00107 }
00108 
00113 cBitmap::cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground)
00114 :cPalette(Bpp)
00115 {
00116   width = Width;
00117   height = Height;
00118   clearWithBackground = ClearWithBackground;
00119   bitmap = NULL;
00120   fontType = fontOsd;
00121   font = NULL;
00122   if (width > 0 && height > 0) {
00123      bitmap = MALLOC(char, width * height);
00124      if (bitmap) {
00125         Clean();
00126         memset(bitmap, 0x00, width * height);
00127         SetFont(fontOsd);
00128         }
00129      else
00130         esyslog("ERROR: can't allocate bitmap!");
00131      }
00132   else
00133      esyslog("ERROR: illegal bitmap parameters (%d, %d)!", width, height);
00134 }
00135 
00136 cBitmap::~cBitmap()
00137 {
00138   delete font;
00139   free(bitmap);
00140 }
00141 
00142 eDvbFont cBitmap::SetFont(eDvbFont Font)
00143 {
00144   eDvbFont oldFont = fontType;
00145   if (fontType != Font || !font) {
00146      delete font;
00147      font = new cFont(Font);
00148      fontType = Font;
00149      }
00150   return oldFont;
00151 }
00152 
00153 bool cBitmap::Dirty(int &x1, int &y1, int &x2, int &y2)
00154 {
00155   if (dirtyX2 >= 0) {
00156      //XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple
00157      //XXX of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
00158      //TODO Fix driver (should be able to handle any size bitmaps!)
00159      while ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) {
00160            if (dirtyX2 < width - 1)
00161               dirtyX2++;
00162            else if (dirtyX1 > 0)
00163               dirtyX1--;
00164            }
00165      //XXX "... / 2" <==> Bpp???
00166      while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
00167            if (dirtyY2 < height - 1)
00168               dirtyY2++;
00169            else if (dirtyY1 > 0)
00170               dirtyY1--;
00171            }
00172      while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
00173            if (dirtyX2 < width - 1)
00174               dirtyX2++;
00175            else if (dirtyX1 > 0)
00176               dirtyX1--;
00177            }
00178      x1 = dirtyX1;
00179      y1 = dirtyY1;
00180      x2 = dirtyX2;
00181      y2 = dirtyY2;
00182      return true;
00183      }
00184   return false;
00185 }
00186 
00187 void cBitmap::Clean(void)
00188 {
00189   dirtyX1 = width;
00190   dirtyY1 = height;
00191   dirtyX2 = -1;
00192   dirtyY2 = -1;
00193 }
00194 
00195 void cBitmap::SetIndex(int x, int y, char Index)
00196 {
00197   if (bitmap) {
00198      if (0 <= x && x < width && 0 <= y && y < height) {
00199         if (bitmap[width * y + x] != Index) {
00200            bitmap[width * y + x] = Index;
00201            if (dirtyX1 > x)  dirtyX1 = x;
00202            if (dirtyY1 > y)  dirtyY1 = y;
00203            if (dirtyX2 < x)  dirtyX2 = x;
00204            if (dirtyY2 < y)  dirtyY2 = y;
00205            }
00206         }
00207      }
00208 }
00209 
00210 void cBitmap::SetPixel(int x, int y, eDvbColor Color)
00211 {
00212   SetIndex(x, y, Index(Color));
00213 }
00214 
00215 void cBitmap::SetBitmap(int x, int y, const cBitmap &Bitmap)
00216 {
00217   if (bitmap && Bitmap.bitmap) {
00218      tIndexes Indexes;
00219      Take(Bitmap, &Indexes);
00220      for (int ix = 0; ix < Bitmap.width; ix++) {
00221          for (int iy = 0; iy < Bitmap.height; iy++)
00222              SetIndex(x + ix, y + iy, Indexes[Bitmap.bitmap[Bitmap.width * iy + ix]]);
00223          }
00224      }
00225 }
00226 
00227 int cBitmap::Width(unsigned char c)
00228 {
00229   return font ? font->Width(c) : -1;
00230 }
00231 
00232 int cBitmap::Width(const char *s)
00233 {
00234   return font ? font->Width(s) : -1;
00235 }
00236 
00237 void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
00238 {
00239   if (bitmap) {
00240      char fg = Index(ColorFg);
00241      char bg = Index(ColorBg);
00242      int h = font->Height(s);
00243      while (s && *s) {
00244            const cFont::tCharData *CharData = font->CharData(*s++);
00245            if (int(x + CharData->width) > width)
00246               break;
00247            for (int row = 0; row < h; row++) {
00248                cFont::tPixelData PixelData = CharData->lines[row];
00249                for (int col = CharData->width; col-- > 0; ) {
00250                    SetIndex(x + col, y + row, (PixelData & 1) ? fg : bg);
00251                    PixelData >>= 1;
00252                    }
00253                }
00254            x += CharData->width;
00255            }
00256      }
00257 }
00258 
00259 void cBitmap::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
00260 {
00261   if (bitmap) {
00262      char c = Index(Color);
00263      for (int y = y1; y <= y2; y++)
00264          for (int x = x1; x <= x2; x++)
00265              SetIndex(x, y, c);
00266      }
00267 }
00268 
00269 void cBitmap::Clear(void)
00270 {
00271   Reset();
00272   if (clearWithBackground)
00273      Fill(0, 0, width - 1, height - 1, clrBackground);
00274 }
00275 
00276 const char *cBitmap::Data(int x, int y)
00277 {
00278   return &bitmap[y * width + x];
00279 }
00280 
00285 cWindow::cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
00286 :cBitmap(w, h, Bpp, ClearWithBackground)
00287 {
00288   handle = Handle;
00289   x0 = x;
00290   y0 = y;
00291   bpp = Bpp;
00292   tiled = Tiled;
00293   shown = false;
00294 }
00295 
00296 bool cWindow::Contains(int x, int y)
00297 {
00298   x -= x0;
00299   y -= y0;
00300   return x >= 0 && y >= 0 && x < width && y < height;
00301 }
00302 
00303 void cWindow::Relocate(int x, int y)
00304 {
00305   x0 = x;
00306   y0 = y;
00307 }
00308 
00309 void cWindow::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
00310 {
00311   if (tiled) {
00312      x1 -= x0;
00313      y1 -= y0;
00314      x2 -= x0;
00315      y2 -= y0;
00316      }
00317   cBitmap::Fill(x1, y1, x2, y2, Color);
00318 }
00319 
00320 void cWindow::SetBitmap(int x, int y, const cBitmap &Bitmap)
00321 {
00322   if (tiled) {
00323      x -= x0;
00324      y -= y0;
00325      }
00326   cBitmap::SetBitmap(x, y, Bitmap);
00327 }
00328 
00329 void cWindow::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
00330 {
00331   if (tiled) {
00332      x -= x0;
00333      y -= y0;
00334      }
00335   cBitmap::Text(x, y, s, ColorFg, ColorBg);
00336 }
00337 
00338 const char *cWindow::Data(int x, int y)
00339 {
00340   return cBitmap::Data(x, y);
00341 }
00342 
00347 cOsdBase::cOsdBase(int x, int y)
00348 {
00349   numWindows = 0;
00350   x0 = x;
00351   y0 = y;
00352 }
00353 
00354 cOsdBase::~cOsdBase()
00355 {
00356   for (int i = 0; i < numWindows; i++)
00357       delete window[i];
00358 }
00359 
00360 tWindowHandle cOsdBase::Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
00361 {
00362   if (numWindows < MAXNUMWINDOWS) {
00363      if (x >= 0 && y >= 0 && w > 0 && h > 0 && (Bpp == 1 || Bpp == 2 || Bpp == 4 || Bpp == 8)) {
00364         if ((w & 0x03) != 0) {
00365            w += 4 - (w & 0x03);
00366            esyslog("ERROR: OSD window width must be a multiple of 4 - increasing to %d", w);
00367            }
00368         cWindow *win = new cWindow(numWindows, x, y, w, h, Bpp, ClearWithBackground, Tiled);
00369         if (OpenWindow(win)) {
00370            window[win->Handle()] = win;
00371            numWindows++;
00372            return win->Handle();
00373            }
00374         else
00375            delete win;
00376         }
00377      else
00378         esyslog("ERROR: illegal OSD parameters");
00379      }
00380   else
00381      esyslog("ERROR: too many OSD windows");
00382   return -1;
00383 }
00384 
00385 void cOsdBase::AddColor(eDvbColor Color, tWindowHandle Window)
00386 {
00387   cWindow *w = GetWindow(Window);
00388   if (w) {
00389      w->Index(Color);
00390      w->Reset();
00391      }
00392 }
00393 
00394 cWindow *cOsdBase::GetWindow(int x, int y)
00395 {
00396   for (int i = 0; i < numWindows; i++) {
00397       if (window[i]->Tiled() && window[i]->Contains(x, y))
00398          return window[i];
00399       }
00400   return NULL;
00401 }
00402 
00403 cWindow *cOsdBase::GetWindow(tWindowHandle Window)
00404 {
00405   if (0 <= Window && Window < numWindows)
00406      return window[Window];
00407   if (Window == LAST_CREATED_WINDOW && numWindows > 0)
00408      return window[numWindows - 1];
00409   return NULL;
00410 }
00411 
00412 void cOsdBase::Flush(void)
00413 {
00414   for (int i = 0; i < numWindows; i++) {
00415       CommitWindow(window[i]);
00416       window[i]->Clean();
00417       }
00422   for (int i = 0; i < numWindows; i++) {
00423       if (!window[i]->Shown())
00424          ShowWindow(window[i]);
00425       }
00426 }
00427 
00428 void cOsdBase::Clear(tWindowHandle Window)
00429 {
00430   if (Window == ALL_TILED_WINDOWS || Window == ALL_WINDOWS) {
00431      for (int i = 0; i < numWindows; i++)
00432          if (Window == ALL_WINDOWS || window[i]->Tiled())
00433             window[i]->Clear();
00434      }
00435   else {
00436      cWindow *w = GetWindow(Window);
00437      if (w)
00438         w->Clear();
00439      }
00440 }
00441 
00442 void cOsdBase::Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window)
00443 {
00444   cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x1, y1) : GetWindow(Window);
00445   if (w)
00446      w->Fill(x1, y1, x2, y2, Color);
00447 }
00448 
00449 void cOsdBase::SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window)
00450 {
00451   cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
00452   if (w)
00453      w->SetBitmap(x, y, Bitmap);
00454 }
00455 
00456 int cOsdBase::Width(unsigned char c)
00457 {
00458   return numWindows ? window[0]->Width(c) : 0;
00459 }
00460 
00461 int cOsdBase::Width(const char *s)
00462 {
00463   return numWindows ? window[0]->Width(s) : 0;
00464 }
00465 
00466 eDvbFont cOsdBase::SetFont(eDvbFont Font)
00467 {
00468   eDvbFont oldFont = Font;
00469   for (int i = 0; i < numWindows; i++)
00470       oldFont = window[i]->SetFont(Font);
00471   return oldFont;
00472 }
00473 
00474 void cOsdBase::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg, tWindowHandle Window)
00475 {
00476   cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
00477   if (w)
00478      w->Text(x, y, s, ColorFg, ColorBg);
00479 }
00480 
00481 void cOsdBase::Relocate(tWindowHandle Window, int x, int y, int NewWidth, int NewHeight)
00482 {
00483   cWindow *w = GetWindow(Window);
00484   if (w) {
00485      if (NewWidth > 0 && NewHeight > 0) {
00486         if ((NewWidth & 0x03) != 0) {
00487            NewWidth += 4 - (NewWidth & 0x03);
00488            esyslog("ERROR: OSD window width must be a multiple of 4 - increasing to %d", NewWidth);
00489            }
00490         CloseWindow(w);
00491         cWindow *NewWindow = new cWindow(w->Handle(), x, y, NewWidth, NewHeight, w->Bpp(), w->ClearWithBackground(), w->Tiled());
00492         window[w->Handle()] = NewWindow;
00493         delete w;
00494         OpenWindow(NewWindow);
00495         }
00496      else {
00497         MoveWindow(w, x, y);
00498         w->Relocate(x, y);
00499         }
00500      }
00501 }
00502 
00503 void cOsdBase::Hide(tWindowHandle Window)
00504 {
00505   HideWindow(GetWindow(Window), true);
00506 }
00507 
00508 void cOsdBase::Show(tWindowHandle Window)
00509 {
00510   HideWindow(GetWindow(Window), false);
00511 }

Generated on Wed Feb 5 23:30:10 2003 for VDR by doxygen1.3-rc2