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