]> git.vomp.tv Git - vompclient.git/blob - boxx.cc
Extended recordings menu, including artwork from tvscraper
[vompclient.git] / boxx.cc
1 /*
2     Copyright 2007 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include <stdlib.h>
22
23 #include "defines.h"
24 #include "bitmap.h"
25 #include "log.h"
26 #include "osd.h"
27
28 #include "boxx.h"
29 #include "surfacevector.h"
30 char Boxx::numBoxxes = 0;
31
32 Boxx::Boxx()
33 {
34   // I want a parent box or a surface.
35   parent = NULL;
36   surface = NULL;
37
38   area.x = 0;
39   area.y = 0;
40   area.w = 0;
41   area.h = 0;
42
43   paraVSpace = 6; // default gap for drawPara
44
45   backgroundColourSet = false;
46   visible = true;
47
48   numBoxxes++;
49   Log::getInstance()->log("Boxx", Log::DEBUG, "Construct, now %u", numBoxxes);
50 }
51
52 Boxx::~Boxx()
53 {
54   if (surface) delete surface;
55   numBoxxes--;
56   Log::getInstance()->log("Boxx", Log::DEBUG, "Destruct, now %u", numBoxxes);
57 }
58
59 void Boxx::draw()
60 {
61   //Log::getInstance()->log("Boxx", Log::DEBUG, "Draw this %p surface %p", this, surface);
62   if (backgroundColourSet) fillColour(backgroundColour);
63
64   Boxx* currentBoxx;
65   vector<Boxx*>::iterator j;
66   //int count=0;
67   for (j = children.begin(); j != children.end(); j++)
68   {
69     currentBoxx = *j;
70    // Log::getInstance()->log("Boxx", Log::DEBUG, "Draw child %d %d", count,currentBoxx);
71     if (currentBoxx->getVisible()) currentBoxx->draw();
72    // count++;
73   }  
74  // Log::getInstance()->log("Boxx", Log::DEBUG, "Draw this %p surface %p End", this, surface);
75 }
76
77 void Boxx::setSize(UINT w, UINT h)
78 {
79   area.w = w;
80   area.h = h;
81 }
82
83 void Boxx::setPosition(UINT x, UINT y)
84 {
85   area.x = x;
86   area.y = y;
87 }
88
89 void Boxx::createBuffer()
90 {
91   surface = Osd::getInstance()->createNewSurface();
92   surface->create(area.w, area.h);
93 }
94
95 void Boxx::add(Boxx* newChild)
96 {
97   newChild->setParent(this);
98   children.push_back(newChild);
99 }
100
101 void Boxx::remove(Boxx* oldChild)
102 {
103   for(vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
104   {
105     if (*i == oldChild)
106     {
107       children.erase(i);
108       return;
109     }
110   }
111   Log::getInstance()->log("Boxx", Log::ERR, "Remove child box called, child %p not found", oldChild);
112 }
113
114 bool Boxx::overlapsVisibleChilds(Region & r)
115 {
116         for(vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
117           {
118             if ((*i)->getVisible() && r.intersects((*i)->getRegionR()))
119             {
120               return true;
121             }
122           }
123         return false;
124 }
125
126 void Boxx::setParent(Boxx* newParent)
127 {
128   parent = newParent;
129 }
130
131 void Boxx::setBackgroundColour(const DrawStyle& Tcolour)
132 {
133   backgroundColour = Tcolour;
134   backgroundColourSet = true;
135 }
136
137 void Boxx::setVisible(bool isVisible)
138 {
139   visible = isVisible;
140 }
141
142 bool Boxx::getVisible()
143 {
144   return visible;
145 }
146
147 void Boxx::setGap(UINT gap)
148 {
149   paraVSpace = gap;
150 }
151
152 void Boxx::blt(Region& r)
153 {
154   /* surface update to screen needs:
155   source x distance into this surface
156   source y distance into this surface
157   width of update
158   height of update
159   destination x on screen
160   destination y on screen
161   */
162
163   if (parent) abort(); // if (parent) then this is a child boxx. It can not blt.
164
165   // this shouldn't be here
166   r.x -= area.x;
167   r.y -= area.y;
168
169   surface->updateToScreen(r.x, r.y, r.w, r.h, area.x + r.x, area.y + r.y);
170
171 }
172
173 int Boxx::getScreenX()
174 {
175   if (parent) return area.x + parent->getScreenX();
176   return area.x;
177 }
178
179 int Boxx::getScreenY()
180 {
181   if (parent) return area.y + parent->getScreenY();
182   return area.y;
183 }
184
185 int Boxx::getRootBoxOffsetX() // convert this to be getX and silently do the parent/not thing? same for Y below?
186 {
187   if (parent) return area.x + parent->getRootBoxOffsetX();
188   return 0;
189 }
190
191 int Boxx::getRootBoxOffsetY()
192 {
193   if (parent) return area.y + parent->getRootBoxOffsetY();
194   return 0;
195 }
196
197 int Boxx::getX()
198 {
199   return area.x;
200 }
201
202 int Boxx::getY()
203 {
204   return area.y;
205 }
206
207 int Boxx::getX2()
208 {
209   return area.x + area.w;
210 }
211
212 int Boxx::getY2()
213 {
214   return area.y + area.h;
215 }
216
217 UINT Boxx::getWidth()
218 {
219   return area.w;
220 }
221
222 UINT Boxx::getHeight()
223 {
224   return area.h;
225 }
226
227 // FIXME Clean up the code to use just one of the following
228
229 Region* Boxx::getRegion()
230 {
231   return &area;
232 }
233
234 Region Boxx::getRegionR()
235 {
236   return area;
237 }
238
239 void Boxx::getRootBoxRegion(Region* r)
240 {
241   // Returns a region that describes the position of this box on the box with the surface
242   // To be used for boxstack->update calls
243
244   r->x = getRootBoxOffsetX();
245   r->y = getRootBoxOffsetY();
246   r->w = area.w;
247   r->h = area.h;  
248 }
249
250 // Level 1 drawing functions
251
252 void Boxx::fillColour(const DrawStyle& colour)
253 {
254   rectangle(0, 0, area.w, area.h, colour);
255 }
256
257 int Boxx::drawPara(const char* text, int x, int y, const DrawStyle& colour,unsigned int skiplines)
258 {
259   char line[256];
260   int lineHeight = getFontHeight() + paraVSpace;
261
262   float lineWidth;
263   float thisCharWidth;
264   int textPos;
265   int linePos;
266   int ypos;
267   int printLine;
268   int leftlines=0;
269
270   int drawLinePos=-skiplines;
271
272   textPos = 0;
273   ypos = y;
274   Region tester;
275   tester.h = lineHeight;
276
277   bool haschildren = true;
278   if ( children.size() == 0) haschildren = false;
279
280   while(1)
281   {
282     linePos = 0;
283     lineWidth = 0;
284     tester.y=ypos;
285     while(1)
286     {
287       printLine = 0;
288       UINT cur_length = 1;
289       wchar_t cur_char = getWChar(text + textPos, &cur_length);
290
291       if (cur_char == '\0') break;
292
293       if (cur_char == '\n')
294       {
295         textPos += cur_length; // ignore the \n
296         printLine = 1;
297         break;
298       }
299       thisCharWidth = charWidth(cur_char);
300       tester.x = lineWidth;
301       tester.w = thisCharWidth + 10;
302
303       if ((lineWidth + thisCharWidth) > (int)(area.w - (2 * paraMargin))
304                   || (haschildren && overlapsVisibleChilds(tester)))
305       {
306         // this character would break the right margin
307         if (cur_char == ' ')
308         {
309           // this char is a space, ignore and break
310           textPos += cur_length;
311           break;
312         }
313         else
314         {
315           // Need to go back to the last space in the line
316           while ((cur_char != ' ') && (linePos >= 0))
317           {
318             textPos -= cur_length;
319             cur_char = getWChar(text + textPos, &cur_length);
320             linePos--;
321           }
322           // Now take the space we just found
323           textPos += cur_length;
324           break;
325         }
326       }
327       for (UINT n = 0; n < cur_length; n++) line[linePos++] = text[textPos + n];
328       lineWidth += thisCharWidth;
329       textPos += cur_length;
330     }
331
332 //    line[linePos++] = '\0';
333     if (linePos >= 0) line[linePos++] = '\0'; //Here is the change
334
335     if (printLine || (linePos > 1)) // if some text was put in line
336     {
337         if (ypos <= (int)(area.h - lineHeight + paraVSpace)) {
338                 if (drawLinePos >= 0) {
339                         drawText(line, x, ypos, colour);
340                         ypos += lineHeight;
341                 }
342         } else {
343                 leftlines++;
344         }
345       drawLinePos++;
346     }
347     else
348     {
349       break;
350     }
351   }
352   return leftlines;
353 }
354
355 void Boxx::rectangle(Region& region, const DrawStyle& colour)
356 {
357   rectangle(region.x, region.y, region.w, region.h, colour);
358 }
359
360 // Level 0 drawing functions
361
362 void Boxx::rectangle(UINT x, UINT y, UINT w, UINT h, const DrawStyle& colour)
363 {
364   if (parent) parent->rectangle(area.x + x, area.y + y, w, h, colour);
365   else surface->fillblt(x, y, w, h, colour);
366 }
367
368 void Boxx::drawText(const char* text, int x, int y, const DrawStyle& colour)
369 {
370   if (parent) parent->drawText(text, area.x + x, area.y + y, colour);
371   else surface->drawText(text, x, y, colour);
372 }
373
374 void Boxx::drawText(const char* text, int x, int y, int width, const DrawStyle& colour)
375 {
376   if (parent) parent->drawText(text, area.x + x, area.y + y, width, colour);
377   else surface->drawText(text, x, y, width, colour);
378 }
379
380 void Boxx::drawTextRJ(const char* text, int x, int y, const DrawStyle& colour)
381 {
382   if (parent) parent->drawTextRJ(text, area.x + x, area.y + y, colour);
383   else surface->drawTextRJ(text, x, y, colour);
384 }
385
386 void Boxx::drawTextCentre(const char* text, int x, int y, const DrawStyle& colour)
387 {
388   if (parent) parent->drawTextCentre(text, area.x + x, area.y + y, colour);
389   else  surface->drawTextCentre(text, x, y, colour);
390 }
391 // Now deprecated
392 /*
393 void Boxx::drawPixelAlpha(UINT x, UINT y, const Colour& colour,bool fastdraw)
394 {
395   if (parent) parent->drawPixelAlpha(area.x + x, area.y + y, colour,fastdraw);
396   else
397   {
398     int c = (  (colour.alpha << 24 )
399              | (colour.red    << 16)
400              | (colour.green  <<  8)
401              | (colour.blue        ) );
402
403     surface->drawPixel(x, y, c,fastdraw);
404   }
405 }
406
407 void Boxx::drawPixel(UINT x, UINT y, const Colour& colour, bool fastdraw)
408 {
409   if (parent) parent->drawPixel(area.x + x, area.y + y, colour,fastdraw);
410   else
411   {
412     int c = (  (0xFF000000         )
413              | (colour.red    << 16)
414              | (colour.green  <<  8)
415              | (colour.blue        ) );
416
417     surface->drawPixel(x, y, c,fastdraw);
418   }
419 }
420 */
421
422 void Boxx::drawTTChar(int ox, int oy,int x, int y, cTeletextChar c)
423 {
424         if (parent) parent->drawTTChar(area.x + ox, area.y + oy, x,y,c);
425         else  if (surface) surface->drawTTChar(ox, oy,x,y,c);
426
427 }
428
429 void Boxx::drawBitmap(UINT x, UINT y, const Bitmap& bm, const DisplayRegion & region)
430 {
431   if (parent) parent->drawBitmap(area.x + x, area.y + y, bm, region);
432   else  if (surface) surface->drawBitmap(x, y, bm, region);
433 }
434
435 void Boxx::drawJpeg(const char *fileName, int x, int y, int *width, int *height)
436 {
437   if (parent) parent->drawJpeg(fileName, area.x + x, area.y + y, width, height);
438   else if (surface) surface->drawJpeg(fileName, x, y, width, height);
439 }
440
441 void Boxx::drawMonoBitmap(UCHAR*base, int dx, int dy, unsigned int height,unsigned int width, DrawStyle& nextColour)
442 {
443   if (parent) parent->drawMonoBitmap(base, area.x +dx, area.y + dy, height, width, nextColour);
444   else if (surface) surface->drawMonoBitmap(base, dx,dy, height, width, nextColour);
445 }
446
447 void Boxx::drawTVMedia(TVMediaInfo & tvmedia,float x, float y, float  width, float height, Corner corner)
448 {
449         if (parent) parent->drawTVMedia(tvmedia,area.x + x,area.y + y,width, height, corner);
450         else if (surface) {
451                 SurfaceVector * surfacevector=dynamic_cast<SurfaceVector*>(surface);
452                 if (surfacevector) surfacevector->drawTVMedia(tvmedia,x, y,width, height, corner);
453                 else surface->fillblt(x, y, width, height, DrawStyle::RED); // Signal that something went wrong
454         }
455
456 }
457
458 void Boxx::drawClippingRectangle(float x, float y, float w, float h)
459 {
460         if (parent) parent->drawClippingRectangle(area.x + x, area.y + y, w, h);
461         else if (surface) {
462                 SurfaceVector * surfacevector=dynamic_cast<SurfaceVector*>(surface);
463                 if (surfacevector) surfacevector->drawClippingRectangle(x, y, w, h);
464
465         }
466 }
467
468 int Boxx::getFontHeight()
469 {
470   if (parent) return parent->getFontHeight();
471   else if (surface) return surface->getFontHeight();
472   else return 18;
473 }
474
475 void Boxx::startFastDraw()
476 {
477   if (parent)
478   {
479     parent->startFastDraw();
480   }
481   else
482   {
483     if (surface) surface->startFastDraw();
484   }
485 }
486
487 void Boxx::endFastDraw()
488 {
489   if (parent)
490   {
491     parent->endFastDraw();
492   }
493   else
494   {
495     if (surface) surface->endFastDraw();
496   }
497 }
498
499 float Boxx::charWidth(wchar_t c)
500 {
501   if (parent) return parent->charWidth(c);
502   else if (surface) return surface->getCharWidth(c);
503   else return 16.; //?
504 }
505
506 wchar_t Boxx::getWChar(const char* str, UINT *length)
507 {
508   if (parent) return parent->getWChar(str, length);
509   else  if (surface) return surface->getWChar(str, length);
510   else return '?'; //?
511 }
512
513 Surface* Boxx::getSurface()
514 {
515   if (parent) return parent->getSurface();
516   return surface;
517 }