]> git.vomp.tv Git - vompclient.git/blob - boxx.cc
Some nasty hacks to support MVP
[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   vdisplay.mode = None;
44
45   paraVSpace = 6; // default gap for drawPara
46
47   backgroundColourSet = false;
48   visible = true;
49
50   numBoxxes++;
51   Log::getInstance()->log("Boxx", Log::DEBUG, "Construct, now %u", numBoxxes);
52 }
53
54 Boxx::~Boxx()
55 {
56   if (surface) delete surface;
57   numBoxxes--;
58   Log::getInstance()->log("Boxx", Log::DEBUG, "Destruct, now %u", numBoxxes);
59 }
60 #include <typeinfo>
61 void Boxx::draw()
62 {
63   //Log::getInstance()->log("Boxx", Log::DEBUG, "Draw this %p surface %p", this, surface);
64   if (backgroundColourSet) fillColour(backgroundColour);
65
66   Boxx* currentBoxx;
67   vector<Boxx*>::iterator j;
68   //int count=0;
69   for (j = children.begin(); j != children.end(); j++)
70   {
71     currentBoxx = *j;
72    //Log::getInstance()->log("Boxx", Log::DEBUG, "Draw child %d %d %s", count,currentBoxx,typeid(*currentBoxx).name());
73     if (currentBoxx->getVisible()) currentBoxx->draw();
74    //Log::getInstance()->log("Boxx", Log::DEBUG, "Draw child %d %d end", count,currentBoxx);
75    // count++;
76   }  
77  // Log::getInstance()->log("Boxx", Log::DEBUG, "Draw this %p surface %p End", this, surface);
78 }
79
80 void Boxx::setSize(UINT w, UINT h)
81 {
82   area.w = w;
83   area.h = h;
84 }
85
86 void Boxx::setPosition(UINT x, UINT y)
87 {
88   area.x = x;
89   area.y = y;
90 }
91
92 void Boxx::createBuffer()
93 {
94   surface = Osd::getInstance()->createNewSurface();
95   surface->create(area.w, area.h);
96 }
97
98 void Boxx::add(Boxx* newChild)
99 {
100   newChild->setParent(this);
101   children.push_back(newChild);
102 }
103
104 void Boxx::remove(Boxx* oldChild)
105 {
106   for(vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
107   {
108     if (*i == oldChild)
109     {
110       children.erase(i);
111       return;
112     }
113   }
114   Log::getInstance()->log("Boxx", Log::ERR, "Remove child box called, child %p not found", oldChild);
115 }
116
117 void Boxx::removeVisibleChilds(Region & r)
118 {
119         for(vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
120         {
121                 if ((*i)->getVisible())
122                 {
123                         Region temp=(*i)->getRegionR();
124                         if (r.intersects(temp)) {
125                                 r=r.subtract(temp);
126                         }
127                 }
128         }
129 }
130
131 void Boxx::setParent(Boxx* newParent)
132 {
133   parent = newParent;
134 }
135
136 void Boxx::setBackgroundColour(const DrawStyle& Tcolour)
137 {
138   backgroundColour = Tcolour;
139   backgroundColourSet = true;
140 }
141
142 void Boxx::setVideoBackground()
143 {
144         vdisplay.mode=Window;
145         vdisplay.fallbackMode=Fullscreen;
146         vdisplay.x=getScreenX();
147         vdisplay.y=getScreenY();
148         vdisplay.width=getWidth();
149         vdisplay.height=getHeight();
150 }
151
152 void Boxx::setVisible(bool isVisible)
153 {
154   visible = isVisible;
155 }
156
157 bool Boxx::getVisible()
158 {
159   return visible;
160 }
161
162 void Boxx::setGap(UINT gap)
163 {
164   paraVSpace = gap;
165 }
166
167 void Boxx::blt(Region& r)
168 {
169   /* surface update to screen needs:
170   source x distance into this surface
171   source y distance into this surface
172   width of update
173   height of update
174   destination x on screen
175   destination y on screen
176   */
177
178   if (parent) abort(); // if (parent) then this is a child boxx. It can not blt.
179
180   // this shouldn't be here
181   r.x -= area.x;
182   r.y -= area.y;
183
184   surface->updateToScreen(r.x, r.y, r.w, r.h, area.x + r.x, area.y + r.y);
185
186 }
187
188 int Boxx::getScreenX()
189 {
190   if (parent) return area.x + parent->getScreenX();
191   return area.x;
192 }
193
194 int Boxx::getScreenY()
195 {
196   if (parent) return area.y + parent->getScreenY();
197   return area.y;
198 }
199
200 int Boxx::getRootBoxOffsetX() // convert this to be getX and silently do the parent/not thing? same for Y below?
201 {
202   if (parent) return area.x + parent->getRootBoxOffsetX();
203   return 0;
204 }
205
206 int Boxx::getRootBoxOffsetY()
207 {
208   if (parent) return area.y + parent->getRootBoxOffsetY();
209   return 0;
210 }
211
212 int Boxx::getX()
213 {
214   return area.x;
215 }
216
217 int Boxx::getY()
218 {
219   return area.y;
220 }
221
222 int Boxx::getX2()
223 {
224   return area.x + area.w;
225 }
226
227 int Boxx::getY2()
228 {
229   return area.y + area.h;
230 }
231
232 UINT Boxx::getWidth()
233 {
234   return area.w;
235 }
236
237 UINT Boxx::getHeight()
238 {
239   return area.h;
240 }
241
242 // FIXME Clean up the code to use just one of the following
243
244 Region* Boxx::getRegion()
245 {
246   return &area;
247 }
248
249 Region Boxx::getRegionR()
250 {
251   return area;
252 }
253
254 void Boxx::getRootBoxRegion(Region* r)
255 {
256   // Returns a region that describes the position of this box on the box with the surface
257   // To be used for boxstack->update calls
258
259   r->x = getRootBoxOffsetX();
260   r->y = getRootBoxOffsetY();
261   r->w = area.w;
262   r->h = area.h;  
263 }
264
265 bool Boxx::getVideoDisplay(VideoDisplay &vd)
266 {
267         for(vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
268         {
269                 if ((*i)->getVideoDisplay(vd)) return true;
270         }
271
272         if (vdisplay.mode==None) return false;
273         vd=vdisplay;
274         return true;
275 }
276
277 // Level 1 drawing functions
278
279 void Boxx::fillColour(const DrawStyle& colour)
280 {
281   rectangle(0, 0, area.w, area.h, colour);
282 }
283
284 int Boxx::drawPara(const char* text, int x, int y, const DrawStyle& colour,unsigned int skiplines)
285 {
286   char line[256];
287   int lineHeight = getFontHeight() + paraVSpace;
288   float lineWidth;
289   float thisCharWidth;
290   int textPos;
291   int textLength;
292   int linePos;
293   int ypos;
294   int printLine;
295   int leftlines=0;
296
297   int drawLinePos=-skiplines;
298
299   textPos = 0;
300   textLength = strlen(text);
301   ypos = y;
302   Region tester;
303
304
305   bool haschildren = true;
306   if ( children.size() == 0) haschildren = false;
307   bool mchar=false;
308   Osd *osd=Osd::getInstance();
309   if (osd->charSet()!=1) mchar=true;
310   float *charwidtharray=NULL;
311 #ifndef VOMP_PLATTFORM_MVP
312 // OSDV
313   OsdVector *osdv=dynamic_cast<OsdVector*>(osd);
314   if (osdv) charwidtharray=osdv->getCharWidthArray();
315 #endif
316   mbstate_t state;
317   memset((void*)&state,0,sizeof(state));
318
319   while(1)
320   {
321     linePos = 0;
322     lineWidth = 0;
323     // tester reinit
324     tester.h = lineHeight;
325     tester.y=ypos;
326     tester.x = x;
327     tester.w = area.w - (2 * paraMargin);
328
329     if (haschildren) removeVisibleChilds(tester);
330
331     while(1)
332     {
333       printLine = 0;
334       int cur_length = 1;
335       wchar_t cur_char;
336       if (*(text + textPos) == '\0') break;
337       if (mchar) {
338           cur_length = mbrtowc(&cur_char, text + textPos, textLength-textPos, &state);
339           if (cur_length <= 0){
340                   cur_char='?';
341                   cur_length=1;
342           }
343       } else cur_char= *(text + textPos);
344
345
346       if (cur_char == '\0') break;
347
348       if (cur_char == '\n')
349       {
350         textPos += cur_length; // ignore the \n
351         printLine = 1;
352         break;
353       }
354
355 #ifndef VOMP_PLATTFORM_MVP
356 // OSDV
357       if (charwidtharray) {
358           thisCharWidth=charwidtharray[cur_char & 0xFF];
359           if (cur_char && 0xFFFFFF00) thisCharWidth=osdv->getCharWidth(cur_char);
360       } else  thisCharWidth = charWidth(cur_char);
361 #else
362       thisCharWidth = charWidth(cur_char);
363 #endif
364
365       if ((lineWidth + thisCharWidth + x) > tester.w)
366       {
367         // this character would break the right margin
368         if (cur_char == ' ')
369         {
370           // this char is a space, ignore and break
371           textPos += cur_length;
372           break;
373         }
374         else
375         {
376           // Need to go back to the last space in the line
377           while ((cur_char != ' ') && (linePos >= 0))
378           {
379             textPos -= cur_length;
380             if (mchar) {
381                   cur_length = mbrtowc(&cur_char, text + textPos, textLength-textPos, &state);
382                   if (cur_length <= 0){
383                         cur_char='?';
384                         cur_length=1;
385                   }
386             } else cur_char= *(text + textPos);
387             linePos--;
388           }
389           // Now take the space we just found
390           textPos += cur_length;
391           break;
392         }
393       }
394       for (int n = 0; n < cur_length; n++) line[linePos++] = text[textPos + n];
395       lineWidth += thisCharWidth;
396       textPos += cur_length;
397     }
398
399 //    line[linePos++] = '\0';
400     if (linePos >= 0) line[linePos++] = '\0'; //Here is the change
401
402     if (printLine || (linePos > 1)) // if some text was put in line
403     {
404         if (ypos <= (int)(area.h - lineHeight + paraVSpace)) {
405                 if (drawLinePos >= 0) {
406                         drawText(line, x, ypos, colour);
407                         ypos += lineHeight;
408                 }
409         } else {
410                 leftlines++;
411         }
412       drawLinePos++;
413     }
414     else
415     {
416       break;
417     }
418   }
419   return leftlines;
420 }
421
422 void Boxx::rectangle(Region& region, const DrawStyle& colour)
423 {
424   rectangle(region.x, region.y, region.w, region.h, colour);
425 }
426
427 // Level 0 drawing functions
428
429 void Boxx::rectangle(UINT x, UINT y, UINT w, UINT h, const DrawStyle& colour)
430 {
431   if (parent) parent->rectangle(area.x + x, area.y + y, w, h, colour);
432   else surface->fillblt(x, y, w, h, colour);
433 }
434
435 void Boxx::drawText(const char* text, int x, int y, const DrawStyle& colour)
436 {
437   if (parent) parent->drawText(text, area.x + x, area.y + y, colour);
438   else surface->drawText(text, x, y, colour);
439 }
440
441 void Boxx::drawText(const char* text, int x, int y, int width, const DrawStyle& colour)
442 {
443   if (parent) parent->drawText(text, area.x + x, area.y + y, width, colour);
444   else surface->drawText(text, x, y, width, colour);
445 }
446
447 void Boxx::drawTextRJ(const char* text, int x, int y, const DrawStyle& colour)
448 {
449   if (parent) parent->drawTextRJ(text, area.x + x, area.y + y, colour);
450   else surface->drawTextRJ(text, x, y, colour);
451 }
452
453 void Boxx::drawTextCentre(const char* text, int x, int y, const DrawStyle& colour)
454 {
455   if (parent) parent->drawTextCentre(text, area.x + x, area.y + y, colour);
456   else  surface->drawTextCentre(text, x, y, colour);
457 }
458 // Now deprecated
459 /*
460 void Boxx::drawPixelAlpha(UINT x, UINT y, const Colour& colour,bool fastdraw)
461 {
462   if (parent) parent->drawPixelAlpha(area.x + x, area.y + y, colour,fastdraw);
463   else
464   {
465     int c = (  (colour.alpha << 24 )
466              | (colour.red    << 16)
467              | (colour.green  <<  8)
468              | (colour.blue        ) );
469
470     surface->drawPixel(x, y, c,fastdraw);
471   }
472 }
473
474 void Boxx::drawPixel(UINT x, UINT y, const Colour& colour, bool fastdraw)
475 {
476   if (parent) parent->drawPixel(area.x + x, area.y + y, colour,fastdraw);
477   else
478   {
479     int c = (  (0xFF000000         )
480              | (colour.red    << 16)
481              | (colour.green  <<  8)
482              | (colour.blue        ) );
483
484     surface->drawPixel(x, y, c,fastdraw);
485   }
486 }
487 */
488
489 void Boxx::drawTTChar(int ox, int oy,int x, int y, cTeletextChar c)
490 {
491         if (parent) parent->drawTTChar(area.x + ox, area.y + oy, x,y,c);
492         else  if (surface) surface->drawTTChar(ox, oy,x,y,c);
493
494 }
495
496 void Boxx::drawBitmap(UINT x, UINT y, const Bitmap& bm, const DisplayRegion & region)
497 {
498   if (parent) parent->drawBitmap(area.x + x, area.y + y, bm, region);
499   else  if (surface) surface->drawBitmap(x, y, bm, region);
500 }
501
502 void Boxx::drawJpeg(const char *fileName, int x, int y, int *width, int *height)
503 {
504   if (parent) parent->drawJpeg(fileName, area.x + x, area.y + y, width, height);
505   else if (surface) surface->drawJpeg(fileName, x, y, width, height);
506 }
507
508 void Boxx::drawMonoBitmap(UCHAR*base, int dx, int dy, unsigned int height,unsigned int width, DrawStyle& nextColour)
509 {
510   if (parent) parent->drawMonoBitmap(base, area.x +dx, area.y + dy, height, width, nextColour);
511   else if (surface) surface->drawMonoBitmap(base, dx,dy, height, width, nextColour);
512 }
513
514 void Boxx::drawTVMedia(TVMediaInfo & tvmedia,float x, float y, float  width, float height, Corner corner)
515 {
516   if (parent) parent->drawTVMedia(tvmedia,area.x + x,area.y + y,width, height, corner);
517   else if (surface)
518   {
519 #ifndef VOMP_PLATTFORM_MVP
520 // OSDV
521     SurfaceVector * surfacevector=dynamic_cast<SurfaceVector*>(surface);
522     if (surfacevector) surfacevector->drawTVMedia(tvmedia,x, y,width, height, corner);
523     else surface->fillblt(x, y, width, height, DrawStyle::RED); // Signal that something went wrong
524 #else
525     surface->fillblt(x, y, width, height, DrawStyle::RED); // Signal that something went wrong
526 #endif
527   }
528 }
529
530 void Boxx::drawClippingRectangle(float x, float y, float w, float h)
531 {
532   if (parent) parent->drawClippingRectangle(area.x + x, area.y + y, w, h);
533   else if (surface)
534   {
535 #ifndef VOMP_PLATTFORM_MVP
536 // OSDV
537     SurfaceVector * surfacevector=dynamic_cast<SurfaceVector*>(surface);
538     if (surfacevector) surfacevector->drawClippingRectangle(x, y, w, h);
539 #endif
540   }
541 }
542
543 int Boxx::getFontHeight()
544 {
545   if (parent) return parent->getFontHeight();
546   else if (surface) return surface->getFontHeight();
547   else return 18;
548 }
549
550 void Boxx::startFastDraw()
551 {
552   if (parent)
553   {
554     parent->startFastDraw();
555   }
556   else
557   {
558     if (surface) surface->startFastDraw();
559   }
560 }
561
562 void Boxx::endFastDraw()
563 {
564   if (parent)
565   {
566     parent->endFastDraw();
567   }
568   else
569   {
570     if (surface) surface->endFastDraw();
571   }
572 }
573
574 float Boxx::charWidth(wchar_t c)
575 {
576   if (parent) return parent->charWidth(c);
577   else if (surface) return surface->getCharWidth(c);
578   else return 16.; //?
579 }
580
581
582 Surface* Boxx::getSurface()
583 {
584   if (parent) return parent->getSurface();
585   return surface;
586 }
587
588 bool Boxx::mouseMove(int x, int y)
589 {
590         if ((x >=  area.x) && (x<area.x2())
591                 && (y >= area.y) && (y < area.y2()))
592         {
593                 return true;
594         }
595         else 
596         {
597                 return false;
598         }
599 }
600
601 bool Boxx::mouseLBDOWN(int x, int y)
602 {
603         if ((x >= area.x) && (x<area.x2())
604                 && (y >= area.y) && (y < area.y2()))
605         {
606                 return true;
607         }
608         else
609         {
610                 return false;
611         }
612 }