2 Copyright 2007-2020 Chris Tallon
4 This file is part of VOMP.
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.
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.
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/>.
28 #include "surfacevector.h"
30 char Boxx::numBoxxes = 0;
37 Log::getInstance()->log("Boxx", Log::DEBUG, "Construct, now %u", numBoxxes);
42 if (surface) delete surface;
44 Log::getInstance()->log("Boxx", Log::DEBUG, "Destruct, now %u", numBoxxes);
49 if (backgroundColourSet) fillColour(backgroundColour);
52 std::vector<Boxx*>::iterator j;
53 for (j = children.begin(); j != children.end(); j++)
56 if (currentBoxx->getVisible()) currentBoxx->draw();
60 void Boxx::setSize(UINT w, UINT h)
66 void Boxx::setPosition(UINT x, UINT y)
72 void Boxx::createBuffer()
74 surface = Osd::getInstance()->createNewSurface();
75 surface->create(area.w, area.h);
78 void Boxx::add(Boxx* newChild)
80 newChild->setParent(this);
81 children.push_back(newChild);
84 void Boxx::remove(Boxx* oldChild)
86 for(std::vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
94 Log::getInstance()->log("Boxx", Log::ERR, "Remove child box called, child %p not found", oldChild);
97 void Boxx::removeVisibleChilds(Region & r)
99 for(std::vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
101 if ((*i)->getVisible())
103 Region temp = (*i)->getRegionR();
104 if (r.intersects(temp)) r = r.subtract(temp);
109 void Boxx::setParent(Boxx* newParent)
114 void Boxx::setBackgroundColour(const DrawStyle& Tcolour)
116 backgroundColour = Tcolour;
117 backgroundColourSet = true;
120 void Boxx::setVideoBackground()
122 vdisplay.mode = Window;
123 vdisplay.fallbackMode = Fullscreen;
124 vdisplay.x = getScreenX();
125 vdisplay.y = getScreenY();
126 vdisplay.width = getWidth();
127 vdisplay.height = getHeight();
130 void Boxx::setVisible(bool isVisible)
135 bool Boxx::getVisible()
140 void Boxx::setGap(UINT gap)
145 void Boxx::blt(Region& r)
147 /* surface update to screen needs:
148 source x distance into this surface
149 source y distance into this surface
152 destination x on screen
153 destination y on screen
156 if (parent) abort(); // if (parent) then this is a child boxx. It can not blt.
158 // this shouldn't be here
162 surface->updateToScreen(r.x, r.y, r.w, r.h, area.x + r.x, area.y + r.y);
165 int Boxx::getScreenX()
167 if (parent) return area.x + parent->getScreenX();
171 int Boxx::getScreenY()
173 if (parent) return area.y + parent->getScreenY();
177 int Boxx::getRootBoxOffsetX() // convert this to be getX and silently do the parent/not thing? same for Y below?
179 if (parent) return area.x + parent->getRootBoxOffsetX();
183 int Boxx::getRootBoxOffsetY()
185 if (parent) return area.y + parent->getRootBoxOffsetY();
201 return area.x + area.w;
206 return area.y + area.h;
209 UINT Boxx::getWidth()
214 UINT Boxx::getHeight()
219 // FIXME Clean up the code to use just one of the following
221 Region* Boxx::getRegion()
226 Region Boxx::getRegionR()
231 void Boxx::getRootBoxRegion(Region* r)
233 // Returns a region that describes the position of this box on the box with the surface
234 // To be used for boxstack->update calls
236 r->x = getRootBoxOffsetX();
237 r->y = getRootBoxOffsetY();
242 bool Boxx::getVideoDisplay(VideoDisplay &vd)
244 for(std::vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
246 if ((*i)->getVideoDisplay(vd)) return true;
249 if (vdisplay.mode == None) return false;
254 // Level 1 drawing functions
256 void Boxx::fillColour(const DrawStyle& colour)
258 rectangle(0, 0, area.w, area.h, colour);
261 int Boxx::drawPara(const char* text, int x, int y, const DrawStyle& colour, unsigned int skiplines)
264 int lineHeight = getFontHeight() + paraVSpace;
276 #pragma warning(disable : 4146)
279 int drawLinePos=-skiplines;
282 textLength = strlen(text);
286 bool haschildren = true;
287 if (children.size() == 0) haschildren = false;
289 Osd *osd = Osd::getInstance();
290 if (osd->charSet() != 1) mchar = true;
291 OsdVector *osdv = dynamic_cast<OsdVector*>(osd);
292 float *charwidtharray = NULL;
293 if (osdv) charwidtharray = osdv->getCharWidthArray();
296 memset(&state, 0, sizeof(state));
303 tester.h = lineHeight;
306 tester.w = area.w - (2 * paraMargin);
308 if (haschildren) removeVisibleChilds(tester);
315 if (*(text + textPos) == '\0') break;
318 cur_length = mbrtowc(&cur_char, text + textPos, textLength-textPos, &state);
327 cur_char = *(text + textPos);
330 if (cur_char == '\0') break;
332 if (cur_char == '\n')
334 textPos += cur_length; // ignore the \n
341 thisCharWidth = charwidtharray[cur_char & 0xFF];
342 if (cur_char && 0xFFFFFF00) thisCharWidth = osdv->getCharWidth(cur_char);
346 thisCharWidth = charWidth(cur_char);
350 if ((lineWidth + thisCharWidth + x) > tester.w)
352 // this character would break the right margin
355 // this char is a space, ignore and break
356 textPos += cur_length;
361 // Need to go back to the last space in the line
362 while ((cur_char != ' ') && (linePos >= 0))
364 textPos -= cur_length;
367 cur_length = mbrtowc(&cur_char, text + textPos, textLength-textPos, &state);
376 cur_char = *(text + textPos);
380 // Now take the space we just found
381 textPos += cur_length;
385 for (int n = 0; n < cur_length; n++) line[linePos++] = text[textPos + n];
386 lineWidth += thisCharWidth;
387 textPos += cur_length;
390 // line[linePos++] = '\0';
391 if (linePos >= 0) line[linePos++] = '\0'; //Here is the change
393 if (printLine || (linePos > 1)) // if some text was put in line
395 if (ypos <= (int)(area.h - lineHeight + paraVSpace))
397 if (drawLinePos >= 0)
399 drawText(line, x, ypos, colour);
417 void Boxx::rectangle(Region& region, const DrawStyle& colour)
419 rectangle(region.x, region.y, region.w, region.h, colour);
422 // Level 0 drawing functions
424 void Boxx::rectangle(UINT x, UINT y, UINT w, UINT h, const DrawStyle& colour)
426 if (parent) parent->rectangle(area.x + x, area.y + y, w, h, colour);
427 else surface->fillblt(x, y, w, h, colour);
430 void Boxx::drawText(const char* text, int x, int y, const DrawStyle& colour)
432 if (parent) parent->drawText(text, area.x + x, area.y + y, colour);
433 else surface->drawText(text, x, y, colour);
436 void Boxx::drawText(const char* text, int x, int y, int width, const DrawStyle& colour)
438 if (parent) parent->drawText(text, area.x + x, area.y + y, width, colour);
439 else surface->drawText(text, x, y, width, colour);
442 void Boxx::drawTextRJ(const char* text, int x, int y, const DrawStyle& colour)
444 if (parent) parent->drawTextRJ(text, area.x + x, area.y + y, colour);
445 else surface->drawTextRJ(text, x, y, colour);
448 void Boxx::drawTextCentre(const char* text, int x, int y, const DrawStyle& colour)
450 if (parent) parent->drawTextCentre(text, area.x + x, area.y + y, colour);
451 else surface->drawTextCentre(text, x, y, colour);
455 void Boxx::drawPixelAlpha(UINT x, UINT y, const Colour& colour,bool fastdraw)
457 if (parent) parent->drawPixelAlpha(area.x + x, area.y + y, colour,fastdraw);
460 int c = ( (colour.alpha << 24 )
462 | (colour.green << 8)
465 surface->drawPixel(x, y, c,fastdraw);
469 void Boxx::drawPixel(UINT x, UINT y, const Colour& colour, bool fastdraw)
471 if (parent) parent->drawPixel(area.x + x, area.y + y, colour,fastdraw);
474 int c = ( (0xFF000000 )
476 | (colour.green << 8)
479 surface->drawPixel(x, y, c,fastdraw);
484 void Boxx::drawTTChar(int ox, int oy,int x, int y, cTeletextChar c)
486 if (parent) parent->drawTTChar(area.x + ox, area.y + oy, x,y,c);
487 else if (surface) surface->drawTTChar(ox, oy,x,y,c);
490 void Boxx::drawBitmap(UINT x, UINT y, const Bitmap& bm, const DisplayRegion & region)
492 if (parent) parent->drawBitmap(area.x + x, area.y + y, bm, region);
493 else if (surface) surface->drawBitmap(x, y, bm, region);
496 void Boxx::drawJpeg(const char *fileName, int x, int y, int *width, int *height)
498 if (parent) parent->drawJpeg(fileName, area.x + x, area.y + y, width, height);
499 else if (surface) surface->drawJpeg(fileName, x, y, width, height);
502 void Boxx::drawMonoBitmap(UCHAR*base, int dx, int dy, unsigned int height,unsigned int width, DrawStyle& nextColour)
504 if (parent) parent->drawMonoBitmap(base, area.x +dx, area.y + dy, height, width, nextColour);
505 else if (surface) surface->drawMonoBitmap(base, dx,dy, height, width, nextColour);
508 void Boxx::drawTVMedia(TVMediaInfo & tvmedia,float x, float y, float width, float height, Corner corner)
510 if (parent) parent->drawTVMedia(tvmedia,area.x + x,area.y + y,width, height, corner);
513 SurfaceVector* surfacevector = dynamic_cast<SurfaceVector*>(surface);
514 if (surfacevector) surfacevector->drawTVMedia(tvmedia, x, y, width, height, corner);
515 else surface->fillblt((int)x, (int)y, (int)width, (int)height, DrawStyle::RED); // Signal that something went wrong
519 void Boxx::drawClippingRectangle(float x, float y, float w, float h)
521 if (parent) parent->drawClippingRectangle(area.x + x, area.y + y, w, h);
524 SurfaceVector* surfacevector = dynamic_cast<SurfaceVector*>(surface);
525 if (surfacevector) surfacevector->drawClippingRectangle(x, y, w, h);
529 int Boxx::getFontHeight()
531 if (parent) return parent->getFontHeight();
532 else if (surface) return surface->getFontHeight();
536 void Boxx::startFastDraw()
540 parent->startFastDraw();
544 if (surface) surface->startFastDraw();
548 void Boxx::endFastDraw()
552 parent->endFastDraw();
556 if (surface) surface->endFastDraw();
560 float Boxx::charWidth(wchar_t c)
562 if (parent) return parent->charWidth(c);
563 else if (surface) return surface->getCharWidth(c);
567 Surface* Boxx::getSurface()
569 if (parent) return parent->getSurface();
573 bool Boxx::mouseMove(int x, int y)
575 if ((x >= (int)area.x) && (x<(int)area.x2())
576 && (y >= (int)area.y) && (y < (int)area.y2()))
586 bool Boxx::mouseLBDOWN(int x, int y)
588 if ((x >= (int)area.x) && (x<(int)area.x2())
589 && (y >= (int)area.y) && (y < (int)area.y2()))
599 bool Boxx::coordsOutsideBox(Message* m)
601 /* Helper function to look at parameter in m, decode the x and y coords
602 * and see if the point is outside this Boxx's area
605 int x = (m->parameter >> 16) - getScreenX();
606 int y = (m->parameter & 0xFFFF) - getScreenY();
610 || (x > static_cast<int>(area.w))
611 || (y > static_cast<int>(area.h))