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 char Boxx::numBoxxes = 0;
38 Log::getInstance()->log("Boxx", Log::DEBUG, "Construct, now %u", numBoxxes);
43 if (surface) delete surface;
45 Log::getInstance()->log("Boxx", Log::DEBUG, "Destruct, now %u", numBoxxes);
50 if (backgroundColourSet) fillColour(backgroundColour);
53 std::vector<Boxx*>::iterator j;
54 for (j = children.begin(); j != children.end(); j++)
57 if (currentBoxx->getVisible()) currentBoxx->draw();
61 void Boxx::setSize(UINT w, UINT h)
67 void Boxx::setPosition(UINT x, UINT y)
73 void Boxx::createBuffer()
75 surface = Osd::getInstance()->createNewSurface();
76 surface->create(area.w, area.h);
79 void Boxx::add(Boxx* newChild)
81 newChild->setParent(this);
82 children.push_back(newChild);
85 void Boxx::remove(Boxx* oldChild)
87 for(std::vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
95 Log::getInstance()->log("Boxx", Log::ERR, "Remove child box called, child %p not found", oldChild);
98 void Boxx::removeVisibleChilds(Region & r)
100 for(std::vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
102 if ((*i)->getVisible())
104 Region temp = (*i)->getRegionR();
105 if (r.intersects(temp)) r = r.subtract(temp);
110 void Boxx::setParent(Boxx* newParent)
115 void Boxx::setBackgroundColour(const DrawStyle& Tcolour)
117 backgroundColour = Tcolour;
118 backgroundColourSet = true;
121 void Boxx::setVideoBackground()
123 vdisplay.mode = Window;
124 vdisplay.fallbackMode = Fullscreen;
125 vdisplay.x = getScreenX();
126 vdisplay.y = getScreenY();
127 vdisplay.width = getWidth();
128 vdisplay.height = getHeight();
131 void Boxx::setVisible(bool isVisible)
136 bool Boxx::getVisible() const
141 void Boxx::setGap(UINT gap)
146 void Boxx::blt(Region& r)
148 /* surface update to screen needs:
149 source x distance into this surface
150 source y distance into this surface
153 destination x on screen
154 destination y on screen
157 if (parent) abort(); // if (parent) then this is a child boxx. It can not blt.
159 // this shouldn't be here
163 surface->updateToScreen(r.x, r.y, r.w, r.h, area.x + r.x, area.y + r.y);
166 int Boxx::getScreenX() const
168 if (parent) return area.x + parent->getScreenX();
172 int Boxx::getScreenY() const
174 if (parent) return area.y + parent->getScreenY();
178 int Boxx::getRootBoxOffsetX() const // convert this to be getX and silently do the parent/not thing? same for Y below?
180 if (parent) return area.x + parent->getRootBoxOffsetX();
184 int Boxx::getRootBoxOffsetY() const
186 if (parent) return area.y + parent->getRootBoxOffsetY();
190 int Boxx::getX() const
195 int Boxx::getY() const
200 int Boxx::getX2() const
202 return area.x + area.w;
205 int Boxx::getY2() const
207 return area.y + area.h;
210 UINT Boxx::getWidth() const
215 UINT Boxx::getHeight() const
220 // FIXME Clean up the code to use just one of the following
222 const Region* Boxx::getRegion() const
227 Region Boxx::getRegionR() const
232 void Boxx::getRootBoxRegion(Region* r) const
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
237 r->x = getRootBoxOffsetX();
238 r->y = getRootBoxOffsetY();
243 bool Boxx::getVideoDisplay(VideoDisplay &vd)
245 for(std::vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
247 if ((*i)->getVideoDisplay(vd)) return true;
250 if (vdisplay.mode == None) return false;
255 // Level 1 drawing functions
257 void Boxx::fillColour(const DrawStyle& colour)
259 rectangle(0, 0, area.w, area.h, colour);
262 int Boxx::drawPara(const char* text, int x, int y, const DrawStyle& colour, unsigned int skiplines)
265 UINT lineHeight = getFontHeight() + paraVSpace;
269 int textLength = strlen(text);
274 int drawLinePos = -skiplines;
278 #pragma warning(disable : 4146)
283 bool haschildren = true;
284 if (children.size() == 0) haschildren = 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();
293 memset(&state, 0, sizeof(state));
300 tester.h = lineHeight;
303 tester.w = area.w - (2 * paraMargin);
305 if (haschildren) removeVisibleChilds(tester);
312 if (*(text + textPos) == '\0') break;
315 cur_length = mbrtowc(&cur_char, text + textPos, textLength-textPos, &state);
324 cur_char = *(text + textPos);
327 if (cur_char == '\0') break;
329 if (cur_char == '\n')
331 textPos += cur_length; // ignore the \n
338 thisCharWidth = charwidtharray[cur_char & 0xFF];
339 if (cur_char && 0xFFFFFF00) thisCharWidth = osdv->getCharWidth(cur_char);
343 thisCharWidth = charWidth(cur_char);
347 if ((lineWidth + thisCharWidth + static_cast<float>(x)) > static_cast<float>(tester.w))
349 // this character would break the right margin
352 // this char is a space, ignore and break
353 textPos += cur_length;
358 // Need to go back to the last space in the line
359 while ((cur_char != ' ') && (linePos >= 0))
361 textPos -= cur_length;
364 cur_length = mbrtowc(&cur_char, text + textPos, textLength-textPos, &state);
373 cur_char = *(text + textPos);
377 // Now take the space we just found
378 textPos += cur_length;
382 for (int n = 0; n < cur_length; n++) line[linePos++] = text[textPos + n];
383 lineWidth += thisCharWidth;
384 textPos += cur_length;
387 // line[linePos++] = '\0';
388 if (linePos >= 0) line[linePos++] = '\0'; //Here is the change
390 if (printLine || (linePos > 1)) // if some text was put in line
392 if (ypos <= (area.h - lineHeight + paraVSpace))
394 if (drawLinePos >= 0)
396 drawText(line, x, ypos, colour);
414 void Boxx::rectangle(Region& region, const DrawStyle& colour)
416 rectangle(region.x, region.y, region.w, region.h, colour);
419 // Level 0 drawing functions
421 void Boxx::rectangle(UINT x, UINT y, UINT w, UINT h, const DrawStyle& colour)
423 if (parent) parent->rectangle(area.x + x, area.y + y, w, h, colour);
424 else surface->fillblt(x, y, w, h, colour);
427 void Boxx::drawText(const char* text, int x, int y, const DrawStyle& colour)
429 if (parent) parent->drawText(text, area.x + x, area.y + y, colour);
430 else surface->drawText(text, x, y, colour);
433 void Boxx::drawText(const char* text, int x, int y, int width, const DrawStyle& colour)
435 if (parent) parent->drawText(text, area.x + x, area.y + y, width, colour);
436 else surface->drawText(text, x, y, width, colour);
439 void Boxx::drawTextRJ(const char* text, int x, int y, const DrawStyle& colour)
441 if (parent) parent->drawTextRJ(text, area.x + x, area.y + y, colour);
442 else surface->drawTextRJ(text, x, y, colour);
445 void Boxx::drawTextCentre(const char* text, int x, int y, const DrawStyle& colour)
447 if (parent) parent->drawTextCentre(text, area.x + x, area.y + y, colour);
448 else surface->drawTextCentre(text, x, y, colour);
452 void Boxx::drawPixelAlpha(UINT x, UINT y, const Colour& colour,bool fastdraw)
454 if (parent) parent->drawPixelAlpha(area.x + x, area.y + y, colour,fastdraw);
457 int c = ( (colour.alpha << 24 )
459 | (colour.green << 8)
462 surface->drawPixel(x, y, c,fastdraw);
466 void Boxx::drawPixel(UINT x, UINT y, const Colour& colour, bool fastdraw)
468 if (parent) parent->drawPixel(area.x + x, area.y + y, colour,fastdraw);
471 int c = ( (0xFF000000 )
473 | (colour.green << 8)
476 surface->drawPixel(x, y, c,fastdraw);
481 void Boxx::drawTTChar(int ox, int oy, int x, int y, cTeletextChar c)
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);
487 void Boxx::drawBitmap(UINT x, UINT y, const Bitmap& bm, const DisplayRegion & region)
489 if (parent) parent->drawBitmap(area.x + x, area.y + y, bm, region);
490 else if (surface) surface->drawBitmap(x, y, bm, region);
493 void Boxx::drawJpeg(const char* fileName, int x, int y, int *width, int *height)
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);
499 void Boxx::drawMonoBitmap(UCHAR* base, int dx, int dy, unsigned int height,unsigned int width, DrawStyle& nextColour)
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);
505 void Boxx::drawTVMedia(TVMediaInfo& tvmedia, float x, float y, float width, float height, Corner corner)
507 if (parent) parent->drawTVMedia(tvmedia, static_cast<float>(area.x) + x, static_cast<float>(area.y) + y, width, height, corner);
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
516 void Boxx::drawClippingRectangle(float x, float y, float w, float h)
518 if (parent) parent->drawClippingRectangle(static_cast<float>(area.x) + x, static_cast<float>(area.y) + y, w, h);
521 SurfaceVector* surfacevector = dynamic_cast<SurfaceVector*>(surface);
522 if (surfacevector) surfacevector->drawClippingRectangle(x, y, w, h);
526 int Boxx::getFontHeight()
528 if (parent) return parent->getFontHeight();
529 else if (surface) return surface->getFontHeight();
533 void Boxx::startFastDraw()
537 parent->startFastDraw();
541 if (surface) surface->startFastDraw();
545 void Boxx::endFastDraw()
549 parent->endFastDraw();
553 if (surface) surface->endFastDraw();
557 float Boxx::charWidth(wchar_t c)
559 if (parent) return parent->charWidth(c);
560 else if (surface) return surface->getCharWidth(c);
564 Surface* Boxx::getSurface()
566 if (parent) return parent->getSurface();
570 bool Boxx::mouseMove(int x, int y)
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())) )
583 bool Boxx::mouseLBDOWN(int x, int y)
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())) )
596 bool Boxx::coordsOutsideBox(Message* m)
598 /* Helper function to look at x and y in m
599 * and see if the point is outside this Boxx's area
602 int x = m->parameter - getScreenX();
603 int y = m->tag - getScreenY();
607 || (x > static_cast<int>(area.w))
608 || (y > static_cast<int>(area.h))