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