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/>.
27 #include "surfacevector.h"
31 static const char* TAG = "Boxx";
33 int Boxx::numBoxxes = 0;
40 LogNT::getInstance()->debug(TAG, "Construct, now {}", numBoxxes);
45 if (surface) delete surface;
47 LogNT::getInstance()->debug(TAG, "Destruct, now {}", numBoxxes);
52 if (backgroundColourSet) fillColour(backgroundColour);
55 std::vector<Boxx*>::iterator j;
56 for (j = children.begin(); j != children.end(); j++)
59 if (currentBoxx->getVisible()) currentBoxx->draw();
63 void Boxx::setSize(UINT w, UINT h)
69 void Boxx::setPosition(UINT x, UINT y)
75 void Boxx::createBuffer()
77 surface = Osd::getInstance()->createNewSurface();
78 surface->create(area.w, area.h);
81 void Boxx::add(Boxx* newChild)
83 newChild->setParent(this);
84 children.push_back(newChild);
87 void Boxx::remove(Boxx* oldChild)
89 for(std::vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
97 LogNT::getInstance()->error(TAG, "Remove child box called, child {} not found", static_cast<void*>(oldChild));
100 void Boxx::removeVisibleChilds(Region & r)
102 for(std::vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
104 if ((*i)->getVisible())
106 Region temp = (*i)->getRegionR();
107 if (r.intersects(temp)) r = r.subtract(temp);
112 void Boxx::setParent(Boxx* newParent)
117 void Boxx::setBackgroundColour(const DrawStyle& Tcolour)
119 backgroundColour = Tcolour;
120 backgroundColourSet = true;
123 void Boxx::setVideoBackground()
125 vdisplay.mode = Window;
126 vdisplay.fallbackMode = Fullscreen;
127 vdisplay.x = getScreenX();
128 vdisplay.y = getScreenY();
129 vdisplay.width = getWidth();
130 vdisplay.height = getHeight();
133 void Boxx::setVisible(bool isVisible)
138 bool Boxx::getVisible() const
143 void Boxx::setGap(UINT gap)
148 void Boxx::blt(Region& r)
150 /* surface update to screen needs:
151 source x distance into this surface
152 source y distance into this surface
155 destination x on screen
156 destination y on screen
159 if (parent) abort(); // if (parent) then this is a child boxx. It can not blt.
161 // this shouldn't be here
165 surface->updateToScreen(r.x, r.y, r.w, r.h, area.x + r.x, area.y + r.y);
168 int Boxx::getScreenX() const
170 if (parent) return area.x + parent->getScreenX();
174 int Boxx::getScreenY() const
176 if (parent) return area.y + parent->getScreenY();
180 int Boxx::getRootBoxOffsetX() const // convert this to be getX and silently do the parent/not thing? same for Y below?
182 if (parent) return area.x + parent->getRootBoxOffsetX();
186 int Boxx::getRootBoxOffsetY() const
188 if (parent) return area.y + parent->getRootBoxOffsetY();
192 int Boxx::getX() const
197 int Boxx::getY() const
202 int Boxx::getX2() const
204 return area.x + area.w;
207 int Boxx::getY2() const
209 return area.y + area.h;
212 UINT Boxx::getWidth() const
217 UINT Boxx::getHeight() const
222 // FIXME Clean up the code to use just one of the following
224 const Region* Boxx::getRegion() const
229 Region Boxx::getRegionR() const
234 void Boxx::getRootBoxRegion(Region* r) const
236 // Returns a region that describes the position of this box on the box with the surface
237 // To be used for boxstack->update calls
239 r->x = getRootBoxOffsetX();
240 r->y = getRootBoxOffsetY();
245 bool Boxx::getVideoDisplay(VideoDisplay &vd)
247 for(std::vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
249 if ((*i)->getVideoDisplay(vd)) return true;
252 if (vdisplay.mode == None) return false;
257 // Level 1 drawing functions
259 void Boxx::fillColour(const DrawStyle& colour)
261 rectangle(0, 0, area.w, area.h, colour);
264 int Boxx::drawPara(const char* text, int x, int y, const DrawStyle& colour, unsigned int skiplines)
267 UINT lineHeight = getFontHeight() + paraVSpace;
271 int textLength = strlen(text);
276 int drawLinePos = -skiplines;
280 #pragma warning(disable : 4146)
285 bool haschildren = true;
286 if (children.size() == 0) haschildren = false;
288 Osd* osd = Osd::getInstance();
289 if (osd->charSet() != 1) mchar = true;
290 OsdVector *osdv = dynamic_cast<OsdVector*>(osd);
291 float* charwidtharray = NULL;
292 if (osdv) charwidtharray = osdv->getCharWidthArray();
295 memset(&state, 0, sizeof(state));
302 tester.h = lineHeight;
305 tester.w = area.w - (2 * paraMargin);
307 if (haschildren) removeVisibleChilds(tester);
314 if (*(text + textPos) == '\0') break;
317 cur_length = mbrtowc(&cur_char, text + textPos, textLength-textPos, &state);
326 cur_char = *(text + textPos);
329 if (cur_char == '\0') break;
331 if (cur_char == '\n')
333 textPos += cur_length; // ignore the \n
340 thisCharWidth = charwidtharray[cur_char & 0xFF];
341 if (cur_char && 0xFFFFFF00) thisCharWidth = osdv->getCharWidth(cur_char);
345 thisCharWidth = charWidth(cur_char);
349 if ((lineWidth + thisCharWidth + static_cast<float>(x)) > static_cast<float>(tester.w))
351 // this character would break the right margin
354 // this char is a space, ignore and break
355 textPos += cur_length;
360 // Need to go back to the last space in the line
361 while ((cur_char != ' ') && (linePos >= 0))
363 textPos -= cur_length;
366 cur_length = mbrtowc(&cur_char, text + textPos, textLength-textPos, &state);
375 cur_char = *(text + textPos);
379 // Now take the space we just found
380 textPos += cur_length;
384 for (int n = 0; n < cur_length; n++) line[linePos++] = text[textPos + n];
385 lineWidth += thisCharWidth;
386 textPos += cur_length;
389 // line[linePos++] = '\0';
390 if (linePos >= 0) line[linePos++] = '\0'; //Here is the change
392 if (printLine || (linePos > 1)) // if some text was put in line
394 if (ypos <= (area.h - lineHeight + paraVSpace))
396 if (drawLinePos >= 0)
398 drawText(line, x, ypos, colour);
416 void Boxx::rectangle(Region& region, const DrawStyle& colour)
418 rectangle(region.x, region.y, region.w, region.h, colour);
421 // Level 0 drawing functions
423 void Boxx::rectangle(UINT x, UINT y, UINT w, UINT h, const DrawStyle& colour)
425 if (parent) parent->rectangle(area.x + x, area.y + y, w, h, colour);
426 else surface->fillblt(x, y, w, h, colour);
429 void Boxx::drawText(const char* text, int x, int y, const DrawStyle& colour)
431 if (parent) parent->drawText(text, area.x + x, area.y + y, colour);
432 else surface->drawText(text, x, y, colour);
435 void Boxx::drawText(const char* text, int x, int y, int width, const DrawStyle& colour)
437 if (parent) parent->drawText(text, area.x + x, area.y + y, width, colour);
438 else surface->drawText(text, x, y, width, colour);
441 void Boxx::drawTextRJ(const char* text, int x, int y, const DrawStyle& colour)
443 if (parent) parent->drawTextRJ(text, area.x + x, area.y + y, colour);
444 else surface->drawTextRJ(text, x, y, colour);
447 void Boxx::drawTextCentre(const char* text, int x, int y, const DrawStyle& colour)
449 if (parent) parent->drawTextCentre(text, area.x + x, area.y + y, colour);
450 else surface->drawTextCentre(text, x, y, colour);
454 void Boxx::drawPixelAlpha(UINT x, UINT y, const Colour& colour,bool fastdraw)
456 if (parent) parent->drawPixelAlpha(area.x + x, area.y + y, colour,fastdraw);
459 int c = ( (colour.alpha << 24 )
461 | (colour.green << 8)
464 surface->drawPixel(x, y, c,fastdraw);
468 void Boxx::drawPixel(UINT x, UINT y, const Colour& colour, bool fastdraw)
470 if (parent) parent->drawPixel(area.x + x, area.y + y, colour,fastdraw);
473 int c = ( (0xFF000000 )
475 | (colour.green << 8)
478 surface->drawPixel(x, y, c,fastdraw);
483 void Boxx::drawTTChar(int ox, int oy, int x, int y, cTeletextChar c)
485 if (parent) parent->drawTTChar(area.x + ox, area.y + oy, x,y,c);
486 else if (surface) surface->drawTTChar(ox, oy,x,y,c);
489 void Boxx::drawBitmap(UINT x, UINT y, const Bitmap& bm, const DisplayRegion & region)
491 if (parent) parent->drawBitmap(area.x + x, area.y + y, bm, region);
492 else if (surface) surface->drawBitmap(x, y, bm, region);
495 void Boxx::drawJpeg(const char* fileName, int x, int y, int *width, int *height)
497 if (parent) parent->drawJpeg(fileName, area.x + x, area.y + y, width, height);
498 else if (surface) surface->drawJpeg(fileName, x, y, width, height);
501 void Boxx::drawMonoBitmap(UCHAR* base, int dx, int dy, unsigned int height,unsigned int width, const DrawStyle& nextColour)
503 if (parent) parent->drawMonoBitmap(base, area.x +dx, area.y + dy, height, width, nextColour);
504 else if (surface) surface->drawMonoBitmap(base, dx,dy, height, width, nextColour);
507 void Boxx::drawTVMedia(TVMediaInfo& tvmedia, float x, float y, float width, float height, Corner corner)
509 if (parent) parent->drawTVMedia(tvmedia, static_cast<float>(area.x) + x, static_cast<float>(area.y) + y, width, height, corner);
512 SurfaceVector* surfacevector = dynamic_cast<SurfaceVector*>(surface);
513 if (surfacevector) surfacevector->drawTVMedia(tvmedia, x, y, width, height, corner);
514 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
518 void Boxx::drawClippingRectangle(float x, float y, float w, float h)
520 if (parent) parent->drawClippingRectangle(static_cast<float>(area.x) + x, static_cast<float>(area.y) + y, w, h);
523 SurfaceVector* surfacevector = dynamic_cast<SurfaceVector*>(surface);
524 if (surfacevector) surfacevector->drawClippingRectangle(x, y, w, h);
528 int Boxx::getFontHeight()
530 if (parent) return parent->getFontHeight();
531 else if (surface) return surface->getFontHeight();
535 void Boxx::startFastDraw()
539 parent->startFastDraw();
543 if (surface) surface->startFastDraw();
547 void Boxx::endFastDraw()
551 parent->endFastDraw();
555 if (surface) surface->endFastDraw();
559 float Boxx::charWidth(wchar_t c)
561 if (parent) return parent->charWidth(c);
562 else if (surface) return surface->getCharWidth(c);
566 Surface* Boxx::getSurface()
568 if (parent) return parent->getSurface();
572 bool Boxx::mouseMove(int x, int y)
574 if ( (x >= static_cast<int>(area.x)) && (x < static_cast<int>(area.x2()))
575 && (y >= static_cast<int>(area.y)) && (y < static_cast<int>(area.y2())) )
585 bool Boxx::mouseLBDOWN(int x, int y)
587 if ( (x >= static_cast<int>(area.x)) && (x < static_cast<int>(area.x2()))
588 && (y >= static_cast<int>(area.y)) && (y < static_cast<int>(area.y2())) )
598 bool Boxx::coordsOutsideBox(Message* m)
600 /* Helper function to look at x and y in m
601 * and see if the point is outside this Boxx's area
604 int x = m->parameter - getScreenX();
605 int y = m->tag - getScreenY();
609 || (x > static_cast<int>(area.w))
610 || (y > static_cast<int>(area.h))