]> git.vomp.tv Git - vompclient.git/blob - boxx.cc
Compile fix for MVP re: location change of hmsf
[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   OsdVector *osdv=dynamic_cast<OsdVector*>(osd);
311   float *charwidtharray=NULL;
312   if (osdv) charwidtharray=osdv->getCharWidthArray();
313
314   mbstate_t state;
315   memset((void*)&state,0,sizeof(state));
316
317   while(1)
318   {
319     linePos = 0;
320     lineWidth = 0;
321     // tester reinit
322     tester.h = lineHeight;
323     tester.y=ypos;
324     tester.x = x;
325     tester.w = area.w - (2 * paraMargin);
326
327     if (haschildren) removeVisibleChilds(tester);
328
329     while(1)
330     {
331       printLine = 0;
332       int cur_length = 1;
333       wchar_t cur_char;
334       if (*(text + textPos) == '\0') break;
335       if (mchar) {
336           cur_length = mbrtowc(&cur_char, text + textPos, textLength-textPos, &state);
337           if (cur_length <= 0){
338                   cur_char='?';
339                   cur_length=1;
340           }
341       } else cur_char= *(text + textPos);
342
343
344       if (cur_char == '\0') break;
345
346       if (cur_char == '\n')
347       {
348         textPos += cur_length; // ignore the \n
349         printLine = 1;
350         break;
351       }
352       if (charwidtharray) {
353           thisCharWidth=charwidtharray[cur_char & 0xFF];
354           if (cur_char && 0xFFFFFF00) thisCharWidth=osdv->getCharWidth(cur_char);
355       } else  thisCharWidth = charWidth(cur_char);
356
357
358
359
360
361       if ((lineWidth + thisCharWidth + x) > tester.w)
362       {
363         // this character would break the right margin
364         if (cur_char == ' ')
365         {
366           // this char is a space, ignore and break
367           textPos += cur_length;
368           break;
369         }
370         else
371         {
372           // Need to go back to the last space in the line
373           while ((cur_char != ' ') && (linePos >= 0))
374           {
375             textPos -= cur_length;
376             if (mchar) {
377                   cur_length = mbrtowc(&cur_char, text + textPos, textLength-textPos, &state);
378                   if (cur_length <= 0){
379                         cur_char='?';
380                         cur_length=1;
381                   }
382             } else cur_char= *(text + textPos);
383             linePos--;
384           }
385           // Now take the space we just found
386           textPos += cur_length;
387           break;
388         }
389       }
390       for (int n = 0; n < cur_length; n++) line[linePos++] = text[textPos + n];
391       lineWidth += thisCharWidth;
392       textPos += cur_length;
393     }
394
395 //    line[linePos++] = '\0';
396     if (linePos >= 0) line[linePos++] = '\0'; //Here is the change
397
398     if (printLine || (linePos > 1)) // if some text was put in line
399     {
400         if (ypos <= (int)(area.h - lineHeight + paraVSpace)) {
401                 if (drawLinePos >= 0) {
402                         drawText(line, x, ypos, colour);
403                         ypos += lineHeight;
404                 }
405         } else {
406                 leftlines++;
407         }
408       drawLinePos++;
409     }
410     else
411     {
412       break;
413     }
414   }
415   return leftlines;
416 }
417
418 void Boxx::rectangle(Region& region, const DrawStyle& colour)
419 {
420   rectangle(region.x, region.y, region.w, region.h, colour);
421 }
422
423 // Level 0 drawing functions
424
425 void Boxx::rectangle(UINT x, UINT y, UINT w, UINT h, const DrawStyle& colour)
426 {
427   if (parent) parent->rectangle(area.x + x, area.y + y, w, h, colour);
428   else surface->fillblt(x, y, w, h, colour);
429 }
430
431 void Boxx::drawText(const char* text, int x, int y, const DrawStyle& colour)
432 {
433   if (parent) parent->drawText(text, area.x + x, area.y + y, colour);
434   else surface->drawText(text, x, y, colour);
435 }
436
437 void Boxx::drawText(const char* text, int x, int y, int width, const DrawStyle& colour)
438 {
439   if (parent) parent->drawText(text, area.x + x, area.y + y, width, colour);
440   else surface->drawText(text, x, y, width, colour);
441 }
442
443 void Boxx::drawTextRJ(const char* text, int x, int y, const DrawStyle& colour)
444 {
445   if (parent) parent->drawTextRJ(text, area.x + x, area.y + y, colour);
446   else surface->drawTextRJ(text, x, y, colour);
447 }
448
449 void Boxx::drawTextCentre(const char* text, int x, int y, const DrawStyle& colour)
450 {
451   if (parent) parent->drawTextCentre(text, area.x + x, area.y + y, colour);
452   else  surface->drawTextCentre(text, x, y, colour);
453 }
454 // Now deprecated
455 /*
456 void Boxx::drawPixelAlpha(UINT x, UINT y, const Colour& colour,bool fastdraw)
457 {
458   if (parent) parent->drawPixelAlpha(area.x + x, area.y + y, colour,fastdraw);
459   else
460   {
461     int c = (  (colour.alpha << 24 )
462              | (colour.red    << 16)
463              | (colour.green  <<  8)
464              | (colour.blue        ) );
465
466     surface->drawPixel(x, y, c,fastdraw);
467   }
468 }
469
470 void Boxx::drawPixel(UINT x, UINT y, const Colour& colour, bool fastdraw)
471 {
472   if (parent) parent->drawPixel(area.x + x, area.y + y, colour,fastdraw);
473   else
474   {
475     int c = (  (0xFF000000         )
476              | (colour.red    << 16)
477              | (colour.green  <<  8)
478              | (colour.blue        ) );
479
480     surface->drawPixel(x, y, c,fastdraw);
481   }
482 }
483 */
484
485 void Boxx::drawTTChar(int ox, int oy,int x, int y, cTeletextChar c)
486 {
487         if (parent) parent->drawTTChar(area.x + ox, area.y + oy, x,y,c);
488         else  if (surface) surface->drawTTChar(ox, oy,x,y,c);
489
490 }
491
492 void Boxx::drawBitmap(UINT x, UINT y, const Bitmap& bm, const DisplayRegion & region)
493 {
494   if (parent) parent->drawBitmap(area.x + x, area.y + y, bm, region);
495   else  if (surface) surface->drawBitmap(x, y, bm, region);
496 }
497
498 void Boxx::drawJpeg(const char *fileName, int x, int y, int *width, int *height)
499 {
500   if (parent) parent->drawJpeg(fileName, area.x + x, area.y + y, width, height);
501   else if (surface) surface->drawJpeg(fileName, x, y, width, height);
502 }
503
504 void Boxx::drawMonoBitmap(UCHAR*base, int dx, int dy, unsigned int height,unsigned int width, DrawStyle& nextColour)
505 {
506   if (parent) parent->drawMonoBitmap(base, area.x +dx, area.y + dy, height, width, nextColour);
507   else if (surface) surface->drawMonoBitmap(base, dx,dy, height, width, nextColour);
508 }
509
510 void Boxx::drawTVMedia(TVMediaInfo & tvmedia,float x, float y, float  width, float height, Corner corner)
511 {
512         if (parent) parent->drawTVMedia(tvmedia,area.x + x,area.y + y,width, height, corner);
513         else if (surface) {
514                 SurfaceVector * surfacevector=dynamic_cast<SurfaceVector*>(surface);
515                 if (surfacevector) surfacevector->drawTVMedia(tvmedia,x, y,width, height, corner);
516                 else surface->fillblt((int)x, (int)y, (int)width, (int)height, DrawStyle::RED); // Signal that something went wrong
517         }
518
519 }
520
521 void Boxx::drawClippingRectangle(float x, float y, float w, float h)
522 {
523         if (parent) parent->drawClippingRectangle(area.x + x, area.y + y, w, h);
524         else if (surface) {
525                 SurfaceVector * surfacevector=dynamic_cast<SurfaceVector*>(surface);
526                 if (surfacevector) surfacevector->drawClippingRectangle(x, y, w, h);
527
528         }
529 }
530
531 int Boxx::getFontHeight()
532 {
533   if (parent) return parent->getFontHeight();
534   else if (surface) return surface->getFontHeight();
535   else return 18;
536 }
537
538 void Boxx::startFastDraw()
539 {
540   if (parent)
541   {
542     parent->startFastDraw();
543   }
544   else
545   {
546     if (surface) surface->startFastDraw();
547   }
548 }
549
550 void Boxx::endFastDraw()
551 {
552   if (parent)
553   {
554     parent->endFastDraw();
555   }
556   else
557   {
558     if (surface) surface->endFastDraw();
559   }
560 }
561
562 float Boxx::charWidth(wchar_t c)
563 {
564   if (parent) return parent->charWidth(c);
565   else if (surface) return surface->getCharWidth(c);
566   else return 16.; //?
567 }
568
569
570 Surface* Boxx::getSurface()
571 {
572   if (parent) return parent->getSurface();
573   return surface;
574 }
575
576 bool Boxx::mouseMove(int x, int y)
577 {
578         if ((x >=  (int)area.x) && (x<(int)area.x2())
579                 && (y >= (int)area.y) && (y < (int)area.y2()))
580         {
581                 return true;
582         }
583         else 
584         {
585                 return false;
586         }
587 }
588
589 bool Boxx::mouseLBDOWN(int x, int y)
590 {
591         if ((x >= (int)area.x) && (x<(int)area.x2())
592                 && (y >= (int)area.y) && (y < (int)area.y2()))
593         {
594                 return true;
595         }
596         else
597         {
598                 return false;
599         }
600 }