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