]> git.vomp.tv Git - vompclient-marten.git/blob - boxx.cc
libCEC support
[vompclient-marten.git] / boxx.cc
1 /*\r
2     Copyright 2007 Chris Tallon\r
3 \r
4     This file is part of VOMP.\r
5 \r
6     VOMP is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     VOMP is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with VOMP; if not, write to the Free Software\r
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
19 */\r
20 \r
21 #include "boxx.h"\r
22 #include "bitmap.h"\r
23 #include "log.h"\r
24 #include "osd.h"\r
25 #include <stdlib.h>\r
26 \r
27 char Boxx::numBoxxes = 0;\r
28 \r
29 Boxx::Boxx()\r
30 {\r
31   // I want a parent box or a surface.\r
32   parent = NULL;\r
33   surface = NULL;\r
34 \r
35   area.x = 0;\r
36   area.y = 0;\r
37   area.w = 0;\r
38   area.h = 0;\r
39 \r
40   paraVSpace = 6; // default gap for drawPara\r
41 \r
42   backgroundColourSet = false;\r
43   visible = true;\r
44 \r
45   numBoxxes++;\r
46   Log::getInstance()->log("Boxx", Log::DEBUG, "Construct, now %u", numBoxxes);\r
47 }\r
48 \r
49 Boxx::~Boxx()\r
50 {\r
51   if (surface) delete surface;\r
52   numBoxxes--;\r
53   Log::getInstance()->log("Boxx", Log::DEBUG, "Destruct, now %u", numBoxxes);\r
54 }\r
55 \r
56 void Boxx::draw()\r
57 {\r
58   //Log::getInstance()->log("Boxx", Log::DEBUG, "Draw this %p surface %p", this, surface);\r
59   if (backgroundColourSet) fillColour(backgroundColour);\r
60 \r
61   Boxx* currentBoxx;\r
62   vector<Boxx*>::iterator j;\r
63   //int count=0;\r
64   for (j = children.begin(); j != children.end(); j++)\r
65   {\r
66     currentBoxx = *j;\r
67    // Log::getInstance()->log("Boxx", Log::DEBUG, "Draw child %d %d", count,currentBoxx);\r
68     if (currentBoxx->getVisible()) currentBoxx->draw();\r
69    // count++;\r
70   }  \r
71  // Log::getInstance()->log("Boxx", Log::DEBUG, "Draw this %p surface %p End", this, surface);\r
72 }\r
73 \r
74 void Boxx::setSize(UINT w, UINT h)\r
75 {\r
76   area.w = w;\r
77   area.h = h;\r
78 }\r
79 \r
80 void Boxx::setPosition(UINT x, UINT y)\r
81 {\r
82   area.x = x;\r
83   area.y = y;\r
84 }\r
85 \r
86 void Boxx::createBuffer()\r
87 {\r
88   surface = Osd::getInstance()->createNewSurface();\r
89   surface->create(area.w, area.h);\r
90 }\r
91 \r
92 void Boxx::add(Boxx* newChild)\r
93 {\r
94   newChild->setParent(this);\r
95   children.push_back(newChild);\r
96 }\r
97 \r
98 void Boxx::remove(Boxx* oldChild)\r
99 {\r
100   for(vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)\r
101   {\r
102     if (*i == oldChild)\r
103     {\r
104       children.erase(i);\r
105       return;\r
106     }\r
107   }\r
108   Log::getInstance()->log("Boxx", Log::ERR, "Remove child box called, child %p not found", oldChild);\r
109 }\r
110 \r
111 void Boxx::setParent(Boxx* newParent)\r
112 {\r
113   parent = newParent;\r
114 }\r
115 \r
116 void Boxx::setBackgroundColour(const Colour& Tcolour)\r
117 {\r
118   backgroundColour = Tcolour;\r
119   backgroundColourSet = true;\r
120 }\r
121 \r
122 void Boxx::setVisible(bool isVisible)\r
123 {\r
124   visible = isVisible;\r
125 }\r
126 \r
127 bool Boxx::getVisible()\r
128 {\r
129   return visible;\r
130 }\r
131 \r
132 void Boxx::setGap(UINT gap)\r
133 {\r
134   paraVSpace = gap;\r
135 }\r
136 \r
137 void Boxx::blt(Region& r)\r
138 {\r
139   /* surface update to screen needs:\r
140   source x distance into this surface\r
141   source y distance into this surface\r
142   width of update\r
143   height of update\r
144   destination x on screen\r
145   destination y on screen\r
146   */\r
147           Log::getInstance()->log("Boxx", Log::DEBUG, "blt mark 1");\r
148   if (parent) abort(); // if (parent) then this is a child boxx. It can not blt.\r
149   Log::getInstance()->log("Boxx", Log::DEBUG, "blt mark 2");\r
150   // this shouldn't be here\r
151   r.x -= area.x;\r
152   r.y -= area.y;\r
153   Log::getInstance()->log("Boxx", Log::DEBUG, "blt mark 3");\r
154   surface->updateToScreen(r.x, r.y, r.w, r.h, area.x + r.x, area.y + r.y);\r
155   Log::getInstance()->log("Boxx", Log::DEBUG, "blt mark 4");\r
156 }\r
157 \r
158 int Boxx::getScreenX()\r
159 {\r
160   if (parent) return area.x + parent->getScreenX();\r
161   return area.x;\r
162 }\r
163 \r
164 int Boxx::getScreenY()\r
165 {\r
166   if (parent) return area.y + parent->getScreenY();\r
167   return area.y;\r
168 }\r
169 \r
170 int Boxx::getRootBoxOffsetX()  // convert this to be getX and silently do the parent/not thing? same for Y below?\r
171 {\r
172   if (parent) return area.x + parent->getRootBoxOffsetX();\r
173   return 0;\r
174 }\r
175 \r
176 int Boxx::getRootBoxOffsetY()\r
177 {\r
178   if (parent) return area.y + parent->getRootBoxOffsetY();\r
179   return 0;\r
180 }\r
181 \r
182 int Boxx::getX()\r
183 {\r
184   return area.x;\r
185 }\r
186 \r
187 int Boxx::getY()\r
188 {\r
189   return area.y;\r
190 }\r
191 \r
192 int Boxx::getX2()\r
193 {\r
194   return area.x + area.w;\r
195 }\r
196 \r
197 int Boxx::getY2()\r
198 {\r
199   return area.y + area.h;\r
200 }\r
201 \r
202 UINT Boxx::getWidth()\r
203 {\r
204   return area.w;\r
205 }\r
206 \r
207 UINT Boxx::getHeight()\r
208 {\r
209   return area.h;\r
210 }\r
211 \r
212 // FIXME Clean up the code to use just one of the following\r
213 \r
214 Region* Boxx::getRegion()\r
215 {\r
216   return &area;\r
217 }\r
218 \r
219 Region Boxx::getRegionR()\r
220 {\r
221   return area;\r
222 }\r
223 \r
224 void Boxx::getRootBoxRegion(Region* r)\r
225 {\r
226   // Returns a region that describes the position of this box on the box with the surface\r
227   // To be used for boxstack->update calls\r
228 \r
229   r->x = getRootBoxOffsetX();\r
230   r->y = getRootBoxOffsetY();\r
231   r->w = area.w;\r
232   r->h = area.h;  \r
233 }\r
234 \r
235 // Level 1 drawing functions\r
236 \r
237 void Boxx::fillColour(const Colour& colour)\r
238 {\r
239   rectangle(0, 0, area.w, area.h, colour);\r
240 }\r
241 \r
242 void Boxx::drawPara(const char* text, int x, int y, const Colour& colour)\r
243 {\r
244   char line[256];\r
245   int lineHeight = getFontHeight() + paraVSpace;\r
246 \r
247   int lineWidth;\r
248   int thisCharWidth;\r
249   int textPos;\r
250   int linePos;\r
251   int ypos;\r
252   int printLine;\r
253 \r
254   textPos = 0;\r
255   ypos = y;\r
256 \r
257   while(1)\r
258   {\r
259     linePos = 0;\r
260     lineWidth = 0;\r
261     while(1)\r
262     {\r
263       printLine = 0;\r
264 \r
265       if (text[textPos] == '\0') break;\r
266 \r
267       if (text[textPos] == '\n')\r
268       {\r
269         textPos++; // ignore the \n\r
270         printLine = 1;\r
271         break;\r
272       }\r
273 \r
274       thisCharWidth = charWidth(text[textPos]);\r
275       if ((lineWidth + thisCharWidth) > (int)(area.w - (2 * paraMargin)))\r
276       {\r
277         // this character would break the right margin\r
278         if (text[textPos] == ' ')\r
279         {\r
280           // this char is a space, ignore and break\r
281           textPos++;\r
282           break;\r
283         }\r
284         else\r
285         {\r
286           // Need to go back to the last space in the line\r
287           while ((text[textPos] != ' ') && (linePos >= 0))\r
288           {\r
289             textPos--;\r
290             linePos--;\r
291           }\r
292           // Now take the space we just found\r
293           textPos++;\r
294           break;\r
295         }\r
296       }\r
297       line[linePos++] = text[textPos];\r
298       lineWidth += thisCharWidth;\r
299       textPos++;\r
300     }\r
301 \r
302 //    line[linePos++] = '\0';\r
303     if (linePos>=0) line[linePos++] = '\0'; //Here is the change\r
304 \r
305     if (printLine || (linePos > 1)) // if some text was put in line\r
306     {\r
307       drawText(line, x, ypos, colour);\r
308       ypos += lineHeight;\r
309       if (ypos > (int)(area.h - lineHeight)) break;\r
310     }\r
311     else\r
312     {\r
313       break;\r
314     }\r
315   }\r
316 }\r
317 \r
318 void Boxx::rectangle(Region& region, const Colour& colour)\r
319 {\r
320   rectangle(region.x, region.y, region.w, region.h, colour);\r
321 }\r
322 \r
323 // Level 0 drawing functions\r
324 \r
325 void Boxx::rectangle(UINT x, UINT y, UINT w, UINT h, const Colour& colour)\r
326 {\r
327   if (parent) parent->rectangle(area.x + x, area.y + y, w, h, colour);\r
328   else surface->fillblt(x, y, w, h, colour.rgba());\r
329 }\r
330 \r
331 void Boxx::drawText(const char* text, int x, int y, const Colour& colour)\r
332 {\r
333   if (parent) parent->drawText(text, area.x + x, area.y + y, colour);\r
334   else surface->drawText(text, x, y, colour.rgba());\r
335 }\r
336 \r
337 void Boxx::drawText(const char* text, int x, int y, int width, const Colour& colour)\r
338 {\r
339   if (parent) parent->drawText(text, area.x + x, area.y + y, width, colour);\r
340   else surface->drawText(text, x, y, width, colour.rgba());\r
341 }\r
342 \r
343 void Boxx::drawTextRJ(const char* text, int x, int y, const Colour& colour)\r
344 {\r
345   if (parent) parent->drawTextRJ(text, area.x + x, area.y + y, colour);\r
346   else surface->drawTextRJ(text, x, y, colour.rgba());\r
347 }\r
348 \r
349 void Boxx::drawTextCentre(const char* text, int x, int y, const Colour& colour)\r
350 {\r
351   if (parent) parent->drawTextCentre(text, area.x + x, area.y + y, colour);\r
352   else  surface->drawTextCentre(text, x, y, colour.rgba());\r
353 }\r
354 \r
355 void Boxx::drawPixelAlpha(UINT x, UINT y, const Colour& colour,bool fastdraw)\r
356 {\r
357   if (parent) parent->drawPixelAlpha(area.x + x, area.y + y, colour,fastdraw);\r
358   else\r
359   {\r
360     int c = (  (colour.alpha << 24 )\r
361              | (colour.red    << 16)\r
362              | (colour.green  <<  8)\r
363              | (colour.blue        ) );\r
364 \r
365     surface->drawPixel(x, y, c,fastdraw);\r
366   }\r
367 }\r
368 \r
369 void Boxx::drawPixel(UINT x, UINT y, const Colour& colour, bool fastdraw)\r
370 {\r
371   if (parent) parent->drawPixel(area.x + x, area.y + y, colour,fastdraw);\r
372   else\r
373   {\r
374     int c = (  (0xFF000000         )\r
375              | (colour.red    << 16)\r
376              | (colour.green  <<  8)\r
377              | (colour.blue        ) );\r
378 \r
379     surface->drawPixel(x, y, c,fastdraw);\r
380   }\r
381 }\r
382 \r
383 void Boxx::drawTTChar(int ox, int oy,int x, int y, cTeletextChar c)\r
384 {\r
385         if (parent) parent->drawTTChar(area.x + ox, area.y + oy, x,y,c);\r
386         else  if (surface) surface->drawTTChar(ox, oy,x,y,c);\r
387 \r
388 }\r
389 \r
390 void Boxx::drawBitmap(UINT x, UINT y, const Bitmap& bm)\r
391 {\r
392   if (parent) parent->drawBitmap(area.x + x, area.y + y, bm);\r
393   else  if (surface) surface->drawBitmap(x, y, bm);\r
394 }\r
395 \r
396 void Boxx::drawJpeg(const char *fileName,int x, int y,int *width, int *height)\r
397 {\r
398         if (parent) parent->drawJpeg(fileName,area.x +x,area.y +y,width,height);\r
399         else if (surface) surface->drawJpeg(fileName,x,y,width,height);\r
400 }\r
401 \r
402 int Boxx::getFontHeight()\r
403 {\r
404         if (parent) return parent->getFontHeight();\r
405         else if (surface) return surface->getFontHeight();\r
406         else return 18;\r
407 }\r
408 \r
409 void Boxx::startFastDraw()\r
410 {\r
411     if (parent) parent->startFastDraw();\r
412     else\r
413     {\r
414          if (surface) surface->startFastDraw();\r
415     }\r
416 }\r
417 \r
418 void Boxx::endFastDraw()\r
419 {\r
420     if (parent) parent->endFastDraw();\r
421     else\r
422     {\r
423         if (surface) surface->endFastDraw();\r
424     }\r
425 }\r
426  \r
427 \r
428 int Boxx::charWidth(char c)\r
429 {\r
430   if (parent) return parent->charWidth(c);\r
431   else  if (surface) return surface->getCharWidth(c);\r
432   else return 10; //?\r
433 }\r
434 \r
435 Surface * Boxx::getSurface() {\r
436   if (parent) return parent->getSurface();\r
437   return surface;\r
438 }\r
439 \r