]> git.vomp.tv Git - vompclient.git/blob - surfacevector.cc
Some more renaming
[vompclient.git] / surfacevector.cc
1 /*
2     Copyright 2012 Marten Richter
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, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include <wchar.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include "bitmap.h"
24 #include "staticartwork.h"
25 #include "surfacevector.h"
26
27 SurfaceVector::SurfaceVector(OsdVector* vosd)
28 {
29   osd = vosd;
30   commands.reserve(2048);
31 }
32
33 SurfaceVector::~SurfaceVector()
34 {
35   osd->removeSurface(this);
36
37   for (SVGCommand& command : commands)
38   {
39     osd->decrementDrawStyleHandleRefCount(command.getHandle()); // We remove the Style reference, so that osd can free stuff // FIXME BUG BUG BUG
40
41     ImageIndex ii = command.getImageIndex();
42     if (ii) osd->removeImageRef(ii);
43
44     LoadIndex li = command.getLoadIndex();
45     if (li) osd->removeLoadIndexRef(li);
46   }
47 }
48
49 int SurfaceVector::getFontHeight()
50 {
51   return (int)osd->getFontHeight();
52 }
53
54 float SurfaceVector::getCharWidth(wchar_t c)
55 {
56   return osd->getCharWidth(c);
57 }
58
59 int SurfaceVector::drawText(const char* text, int x, int y, const DrawStyle& c)
60 {
61   return drawText(text, x, y, 0, c);
62 }
63
64 int SurfaceVector::drawText(const char* text, int x, int y, int width, const DrawStyle& c)
65 {
66   float shift = 0.;
67   const char* run = text;
68   size_t length = strlen(text);
69
70
71   command_mutex.lock();
72
73   VectorHandle ref;
74   float* charwidtharray = osd->getCharWidthArray();
75   int commands_size = commands.size();
76   int chars = 0;
77   commands.resize(commands_size + strlen(text));
78 #ifndef WIN32
79   mbstate_t state;
80   wchar_t tempo;
81   size_t num_bytes = 1;
82   memset((void*)&state, 0, sizeof(state));
83   num_bytes = mbrtowc(&tempo, run, length, &state);
84
85   while (num_bytes != ((size_t) -1) && num_bytes != ((size_t) -2) && length > 0)
86   {
87     ref = osd->getDrawStyleHandle(c); // Need to call this each time to have OSD get the ref count right. Maybe expose incRefCount sometime
88     SVGCommand::PaintGlyph(commands[commands_size + chars], x + shift, y, tempo, ref);
89     chars++;
90
91     float cur_shift = charwidtharray[tempo & 0xFF];
92
93     if (tempo && 0xFFFFFF00) cur_shift = osd->getCharWidth(tempo);
94
95     shift += cur_shift;
96     length -= num_bytes;
97     run += num_bytes;
98
99     if (shift > width && width > 0)
100     {
101       command_mutex.unlock();
102       return 1;
103     }
104
105     num_bytes = mbrtowc(&tempo, run, length, &state);
106   }
107
108 #else
109   wchar_t* temptext = new wchar_t[length + 1];
110   int real_length = MultiByteToWideChar(CP_UTF8, 0, text, -1,
111                                         temptext, length + 1) - 1;
112
113   for (int i = 0; i < real_length; i++)
114   {
115     ref = osd->getDrawStyleHandle(c); // Need to call this each time to have OSD get the ref count right. Maybe expose incRefCount sometime
116     SVGCommand::PaintGlyph(commands[commands_size + chars], x + shift, y, temptext[i], ref);
117     chars++;
118
119     float cur_shift = charwidtharray[temptext[i] & 0xFF];
120
121     if (temptext[i] && 0xFFFFFF00) cur_shift = osd->getCharWidth(temptext[i]);
122
123     shift += cur_shift;
124   }
125
126   delete[] temptext;
127 #endif
128
129   commands.resize(commands_size + chars);
130   command_mutex.unlock();
131   return 1;
132
133 }
134 int SurfaceVector::drawTextRJ(const char* text, int x, int y, const DrawStyle& c)
135 {
136   float shift = 0.;
137   const char* run = text;
138   size_t length = strlen(text);
139
140 #ifndef WIN32
141   mbstate_t state;
142   wchar_t tempo[1];
143   size_t num_bytes = 1;
144   memset((void*)&state, 0, sizeof(state));
145   num_bytes = mbrtowc(tempo, run, length, &state);
146
147   while (num_bytes != ((size_t) -1) && num_bytes != ((size_t) -2) && length > 0)
148   {
149     shift += osd->getCharWidth(*tempo);
150     length -= num_bytes;
151     run += num_bytes;
152     num_bytes = mbrtowc(tempo, run, length, &state);
153   }
154
155 #else
156   wchar_t* temptext = new wchar_t[length + 1];
157   int real_length = MultiByteToWideChar(CP_UTF8, 0, text, -1,
158                                         temptext, length + 1) - 1;
159
160   for (int i = 0; i < real_length; i++)
161   {
162     shift += osd->getCharWidth(temptext[i]);
163   }
164
165   delete[] temptext;
166 #endif
167   return drawText(text, (int)(x - shift), y, c);
168 }
169
170 int SurfaceVector::drawTextCentre(const char* text, int x, int y, const DrawStyle& c)
171 {
172   float shift = 0;
173   const char* run = text;
174   size_t length = strlen(text);
175
176 #ifndef WIN32
177   mbstate_t state;
178   wchar_t tempo[1];
179   size_t num_bytes = 1;
180   memset((void*)&state, 0, sizeof(state));
181   num_bytes = mbrtowc(tempo, run, length, &state);
182
183   while (num_bytes != ((size_t) -1) && num_bytes != ((size_t) -2) && length > 0)
184   {
185     shift += osd->getCharWidth(*tempo);
186     length -= num_bytes;
187     run += num_bytes;
188     num_bytes = mbrtowc(tempo, run, length, &state);
189   }
190
191 #else
192   wchar_t* temptext = new wchar_t[length + 1];
193   int real_length = MultiByteToWideChar(CP_UTF8, 0, text, -1,
194                                         temptext, length + 1) - 1;
195
196   for (int i = 0; i < real_length; i++)
197   {
198     shift += osd->getCharWidth(temptext[i]);
199   }
200
201   delete[] temptext;
202 #endif
203
204   return drawText(text, (int)(x - shift / 2.),  y, c);
205 }
206
207 void SurfaceVector::drawJpeg(const char* fileName, int x, int y, int* width, int* height)
208 {
209   StaticArtwork index = sa_MAX; // This is for compatibility only
210
211   if (strcmp(fileName, "/vdr.jpg") == 0)
212   {
213     index = sa_vdrlogo;
214     *height = 100; // this is faked so that the system does use the old coordinate system
215     *width = (int)ceil(190.f * osd->getPixelAspect());
216   }
217   else if (strcmp(fileName, "/wallpaperPAL.jpg") == 0)
218   {
219     index = sa_wallpaper;
220     *width = 720; // this is faked so that the system does use the old coordinate system
221     *height = 576;
222   }
223
224   if (index != sa_MAX)
225   {
226     TVMediaInfo info;
227     info.setStaticArtwork(index);
228     drawTVMedia(info, x, y, *width, *height, TopLeft);
229   }
230 }
231
232 /*
233 void SurfaceVector::drawJpeg(const char *fileName,int x, int y,int *width, int *height)
234 {
235         command_mutex.lock();
236         ImageIndex image=osd->getJpegRef(fileName,width,height);
237         commands.push_back(SVGCommand::PaintImage(x,y,*width,*height,image,0));
238         command_mutex.unlock();
239 }
240 */
241
242 void SurfaceVector::drawTVMedia(TVMediaInfo& tvmedia, float x, float y, float  width, float height, Corner corner)
243 {
244   command_mutex.lock();
245   ImageIndex image = 0;
246   LoadIndex load_index = osd->getTVMediaRef(tvmedia, image);
247
248   if (width != 0 && height != 0)
249   {
250     removeCommands(x, y, width, height);
251   }
252
253   if (image)
254   {
255     //Log::getInstance()->log("SurfaceVector", Log::DEBUG, "TVMedia Add instru image %d %d", load_index,image);
256     commands.push_back(SVGCommand::PaintImage(x, y, width, height, image, 0, corner));
257   }
258   else
259   {
260
261     commands.push_back(SVGCommand::PaintImageLoading(load_index, x, y, width, height, corner));
262     //Log::getInstance()->log("SurfaceVector", Log::DEBUG, "TVMedia Add instru image loading %d %d", load_index,image);
263   }
264
265   command_mutex.unlock();
266 }
267
268 void SurfaceVector::drawClippingRectangle(float x, float y, float w, float h)
269 {
270   command_mutex.lock();
271   commands.push_back(SVGCommand::PaintClipping((float)x, (float)y, (float)w, (float)h));
272   command_mutex.unlock();
273 }
274
275 int SurfaceVector::create(UINT width, UINT height)
276 {
277   sheight = height;
278   swidth = width;
279   return 1;
280 }
281 void SurfaceVector::display()
282 {
283   //nothing this is really mvp specific  // FIXME remove?
284 }
285
286 int SurfaceVector::fillblt(int x, int y, int width, int height, const DrawStyle& c)
287 {
288   command_mutex.lock();
289   removeCommands(x, y, width, height); // remove commands below the box
290   VectorHandle ref = osd->getDrawStyleHandle(c);
291   commands.push_back(SVGCommand::PaintPath(x, y, width, height, PIRectangle, ref));
292   command_mutex.unlock();
293   return 1;
294
295 }
296 void SurfaceVector::drawHorzLine(int x1, int x2, int y, const DrawStyle& c)
297 {
298   command_mutex.lock();
299   VectorHandle ref = osd->getDrawStyleHandle(c);
300   commands.push_back(SVGCommand::PaintPath(x1, y, x2 - x1, 1, PIHorzLine, ref));
301   command_mutex.unlock();
302 }
303
304 void SurfaceVector::drawVertLine(int x, int y1, int y2, const DrawStyle& c)
305 {
306   command_mutex.lock();
307   VectorHandle ref = osd->getDrawStyleHandle(c);
308   commands.push_back(SVGCommand::PaintPath(x, y1, 1, y2 - y1, PIVertLine, ref));
309   command_mutex.unlock();
310 }
311
312 void SurfaceVector::drawBitmap(int x, int y, const Bitmap& bm, const DisplayRegion& region)
313 {
314   //this is complicated
315   command_mutex.lock();
316   /*
317         unsigned int * data=(unsigned int*)malloc(sizeof(unsigned int)*bm.getWidth()*bm.getHeight());
318         for (UINT j = 0; j < bm.getHeight(); ++j){
319            for (UINT i = 0; i < bm.getWidth(); ++i)
320            {
321                    data[i+j*bm.getHeight()]=bm.getColour(i,j);
322            }
323       }*/
324   ImageIndex image = osd->getImagePalette(bm.getWidth(), bm.getHeight(), &(bm.rawData()[0]),
325                                           (const unsigned int*)&bm.palette.getColourVector()[0]); // data is freed by the OSD
326   //free(data);
327   float tx = x + region.windowx;
328   float ty = y + region.windowy;
329   float th = bm.getHeight();
330   float tw = bm.getWidth();
331
332   float scalex = 720.f / ((float) (region.framewidth + 1));
333   float scaley = 576.f / ((float) (region.frameheight + 1));
334   tx *= scalex;
335   ty *= scaley;
336   tw *= scalex;
337   th *= scaley;
338   SVGCommand temp = SVGCommand::PaintImage(tx, ty, tw, th, image, 0);
339   removeCommands(tx, ty, tw, th);
340   commands.push_back(temp);
341   command_mutex.unlock();
342 }
343
344 void SurfaceVector::drawPoint(int x, int y, DrawStyle& c, bool fastdraw)
345 {
346   if (!fastdraw) command_mutex.lock();
347
348   VectorHandle ref = osd->getDrawStyleHandle(c);
349   commands.push_back(SVGCommand::PaintPath(x, y, 1, 1, PIPoint, ref));
350
351   if (!fastdraw)  command_mutex.unlock();
352 }
353 void SurfaceVector::drawMonoBitmap(UCHAR* base, int dx, int dy, unsigned int height, unsigned int width, DrawStyle& nextColour)
354 {
355   command_mutex.lock();
356   ImageIndex image = osd->getMonoBitmapRef(base, width, height);
357   VectorHandle ref = osd->getDrawStyleHandle(nextColour);
358   removeCommands(dx, dy, width, height);
359   commands.push_back(SVGCommand::PaintImage(dx, dy, height, width, image, ref)); // FIXME BUG height and width wrong way around?
360   command_mutex.unlock();
361 }
362
363
364 int SurfaceVector::removeCommands(float x, float y, float width, float height)
365 {
366   // we iterate through all old commands in order to remove commands hidden by this rectangle
367   std::vector<SVGCommand>::iterator itty = commands.begin();
368   std::vector<SVGCommand>::iterator remstart;
369   bool remove = false;
370   float cx, cy, cw, ch;
371   cx = cy = 0.f;
372   cw = swidth;
373   ch = sheight;
374   bool clipping_erases = false;
375
376   while (itty != commands.end())
377   {
378     if ((clipping_erases // test if clipping helps
379          || (*itty).Test(x, y, width, height)  )
380         && (*itty).instr != DrawClipping)
381     {
382       //Log::getInstance()->log("OSD", Log::DEBUG, "Remove command %d %g %g %g %g %d %d",(*itty).instr,
383       //(*itty).x,(*itty).y,(*itty).w,(*itty).h,(*itty).handle,(*itty).target.image);
384       osd->decrementDrawStyleHandleRefCount((*itty).getHandle()); // We remove the Style reference, so that osd can free stuff // FIXME BUG BUG BUG
385       ImageIndex ii = (*itty).getImageIndex();
386
387       if (ii) osd->removeImageRef(ii);
388
389       LoadIndex li = (*itty).getLoadIndex();
390
391       if (li) osd->removeLoadIndexRef(li);
392
393       if (!remove)
394       {
395         remstart = itty;
396         remove = true;
397       }
398     }
399     else
400     {
401       if ((*itty).instr == DrawClipping)
402       {
403         if ((*itty).w == 0.f && (*itty).h == 0.f)
404         {
405           cx = cy = 0.f;
406           cw = swidth;
407           ch = sheight;
408
409         }
410         else
411         {
412           cx = (*itty).x;
413           cy = (*itty).y;
414           cw = (*itty).w;
415           ch = (*itty).h;
416         }
417
418         clipping_erases = (cx >= x) && (cy >= y) && ((cx + cw) <= (x + width)) && ((cy + ch) <= (y + height));
419       }
420
421       if (remove)
422       {
423         itty = commands.erase(remstart, itty);
424         remove = false;
425       }
426     }
427
428     itty++;
429   }
430
431   if (remove)
432   {
433     itty = commands.erase(remstart, itty);
434   }
435
436   return 1;
437
438 }
439
440 int SurfaceVector::updateToScreen(int sx, int sy, int w, int h, int dx, int dy)
441 {
442   // ok this method really works in a pixel oriented way
443   command_mutex.lock();
444   osd->updateOrAddSurface(this, dx - sx, dy - sy, swidth, sheight, commands);
445   command_mutex.unlock();
446   return 1;
447 }
448
449
450 /* This is for systems which need a locking of the drawing surface to speed up drawing */
451 void SurfaceVector::startFastDraw()
452 {
453   command_mutex.lock();
454 }
455 void SurfaceVector::endFastDraw()
456 {
457   command_mutex.unlock();
458 }
459
460
461 void SurfaceVector::drawTTChar(int ox, int oy, int x, int y, cTeletextChar c)
462 {
463   command_mutex.lock();
464   std::vector<SVGCommand>::iterator itty = commands.begin();
465
466   while (itty != commands.end())
467   {
468     if ((*itty).TTTest(ox, oy, x, y) )
469     {
470       itty = commands.erase(itty);
471       break;
472     }
473     else
474     {
475       itty++;
476     }
477   }
478
479   commands.push_back(SVGCommand::PaintTTchar(ox, oy, x, y, c.getInternal()));
480   command_mutex.unlock();
481 }