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