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