]> git.vomp.tv Git - vompclient.git/blob - surfacevector.cc
Fix leak in picture handling of osdvector, add static fallback pictures, some default...
[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 }
33
34 SurfaceVector::~SurfaceVector()
35 {
36         osd->removeSurface(this);
37         list<SVGCommand>::iterator itty=commands.begin();
38         while (itty!=commands.end())
39         {
40                 osd->removeStyleRef((*itty).getRef()); // We remove the Style reference, so that osd can free stuff
41                 ImageIndex ii=(*itty).getImageIndex();
42                 if (ii) {
43                         osd->removeImageRef(ii);
44                 }
45                 LoadIndex li=(*itty).getLoadIndex();
46                 if (li) osd->removeLoadIndexRef(li);
47                 itty++;
48         }
49 }
50
51
52 int SurfaceVector::getFontHeight()
53 {
54         return osd->getFontHeight();
55 }
56
57 float SurfaceVector::getCharWidth(wchar_t c)
58 {
59         return osd->getCharWidth(c);
60 }
61
62 wchar_t SurfaceVector::getWChar(const char* str, unsigned int *length)
63 {
64         int mlength=0;
65         int max_length=4;
66         wchar_t tempo[1];
67         size_t num_bytes=1;
68         if (str[0]=='\0') {
69                 *length=1;
70                 return '\0';
71         } else if (str[1]=='\0'){
72                 max_length=2;
73         } else if (str[2]=='\0'){
74                 max_length=3;
75         }
76         mbstate_t state;
77         memset((void*)&state,0,sizeof(state));
78         num_bytes=mbrtowc(tempo, str, max_length, &state);
79         if (num_bytes!=((size_t) -1) && num_bytes!=((size_t) -2))
80         {
81                 *length=num_bytes;
82                 return *tempo;
83         }
84         *length=1;
85         return '?';
86 }
87
88
89 int SurfaceVector::drawText(const char* text, int x, int y, const DrawStyle& c){
90         return drawText(text, x, y, 0, c);
91 }
92
93 int SurfaceVector::drawText(const char* text, int x, int y, int width, const DrawStyle& c)
94 {
95         float shift=0.;
96         const char *run=text;
97         mbstate_t state;
98         wchar_t tempo[1];
99         size_t num_bytes=1;
100         size_t length=strlen(text);
101         memset((void*)&state,0,sizeof(state));
102         command_mutex.Lock();
103         num_bytes=mbrtowc(tempo, run, length, &state);
104         while (num_bytes!=((size_t) -1) && num_bytes!=((size_t) -2) && length>0)
105         {
106                 unsigned int ref=osd->getStyleRef(c);
107                 commands.push_back(SVGCommand::PaintGlyph(x+shift,y,*tempo,ref));
108                 shift+=osd->getCharWidth(*tempo);
109                 length -= num_bytes;
110                 run += num_bytes;
111                 if (shift>width && width >0) {
112                         command_mutex.Unlock();
113                         return 1;
114                 }
115                 num_bytes=mbrtowc(tempo, run, length, &state);
116         }
117         command_mutex.Unlock();
118         return 1;
119
120 }
121 int SurfaceVector::drawTextRJ(const char* text, int x, int y, const DrawStyle& c)
122 {
123         float shift=0.;
124         const char *run=text;
125         mbstate_t state;
126         wchar_t tempo[1];
127         size_t num_bytes=1;
128         size_t length=strlen(text);
129         memset((void*)&state,0,sizeof(state));
130
131         num_bytes=mbrtowc(tempo, run, length, &state);
132         while (num_bytes!=((size_t) -1) && num_bytes!=((size_t) -2) && length>0)
133         {
134                 shift+=osd->getCharWidth(*tempo);
135                 length -= num_bytes;
136                 run += num_bytes;
137                 num_bytes=mbrtowc(tempo, run, length, &state);
138         }
139         return drawText(text, x-shift,  y, c);
140 }
141
142 int SurfaceVector::drawTextCentre(const char* text, int x, int y, const DrawStyle& c)
143 {
144         float shift=0;
145         const char *run=text;
146         mbstate_t state;
147         wchar_t tempo[1];
148         size_t num_bytes=1;
149         size_t length=strlen(text);
150         memset((void*)&state,0,sizeof(state));
151
152         num_bytes=mbrtowc(tempo, run, length, &state);
153         while (num_bytes!=((size_t) -1) && num_bytes!=((size_t) -2) && length>0)
154         {
155                 shift+=osd->getCharWidth(*tempo);
156                 length -= num_bytes;
157                 run += num_bytes;
158                 num_bytes=mbrtowc(tempo, run, length, &state);
159         }
160         return drawText(text, x-shift/2.,  y, c);
161 }
162
163 void SurfaceVector::drawJpeg(const char *fileName,int x, int y,int *width, int *height)
164 {
165         StaticArtwork index=sa_MAX; // This is for compatibility only
166         if (strcmp(fileName,"/vdr.jpg")==0) {
167                 index=sa_vdrlogo;
168                 *height=100; // this is faked so that the system does use the old coordinate system
169                 *width=ceil(190.f*osd->getPixelAspect());
170         } else if (strcmp(fileName,"/wallpaperPAL.jpg")==0) {
171                 index=sa_wallpaper;
172                 *width=720; // this is faked so that the system does use the old coordinate system
173                 *height=576;
174         }
175         if (index!=sa_MAX) {
176                 TVMediaInfo info;
177                 info.setStaticArtwork(index);
178                 drawTVMedia(info,x,y,*width,*height,TopLeft);
179         }
180 }
181
182 /*
183 void SurfaceVector::drawJpeg(const char *fileName,int x, int y,int *width, int *height)
184 {
185         command_mutex.Lock();
186         ImageIndex image=osd->getJpegRef(fileName,width,height);
187         commands.push_back(SVGCommand::PaintImage(x,y,*width,*height,image,0));
188         command_mutex.Unlock();
189 }
190 */
191
192 void SurfaceVector::drawTVMedia(TVMediaInfo & tvmedia,float x, float y, float  width, float height, Corner corner)
193 {
194         command_mutex.Lock();
195         ImageIndex image=0;
196         LoadIndex load_index=osd->getTVMediaRef(tvmedia,image);
197         if (width!=0 && height!=0) {
198                 removeCommands(x,y,width,height);
199         }
200         if (image) {
201                 //Log::getInstance()->log("SurfaceVector", Log::DEBUG, "TVMedia Add instru image %d %d", load_index,image);
202                 commands.push_back(SVGCommand::PaintImage(x,y,width,height,image,0,corner));
203         } else {
204
205                 commands.push_back(SVGCommand::PaintImageLoading(load_index,x,y,width,height,0,corner));
206                 //Log::getInstance()->log("SurfaceVector", Log::DEBUG, "TVMedia Add instru image loading %d %d", load_index,image);
207         }
208         command_mutex.Unlock();
209 }
210
211 void SurfaceVector::drawClippingRectangle(float x, float y, float w, float h)
212 {
213         command_mutex.Lock();
214         commands.push_back(SVGCommand::PaintClipping((float)x,(float)y,(float)w,(float)h));
215         command_mutex.Unlock();
216 }
217
218 int SurfaceVector::create(UINT width, UINT height)
219 {
220         sheight=height;
221         swidth=width;
222         return 1;
223 }
224 void SurfaceVector::display()
225 {
226         //nothing this is really mvp specific
227 }
228
229 int SurfaceVector::fillblt(int x, int y, int width, int height, const DrawStyle& c)
230 {
231         command_mutex.Lock();
232         removeCommands(x,y,width,height); // remove commands below the box
233         unsigned int ref=osd->getStyleRef(c);
234         commands.push_back(SVGCommand::PaintPath(x,y,width,height,Rectangle,ref));
235         command_mutex.Unlock();
236         return 1;
237
238 }
239 void SurfaceVector::drawHorzLine(int x1, int x2, int y, const DrawStyle& c)
240 {
241         command_mutex.Lock();
242         unsigned int ref=osd->getStyleRef(c);
243         commands.push_back(SVGCommand::PaintPath(x1,y,x2-x1,1,HorzLine,ref));
244         command_mutex.Unlock();
245 }
246
247 void SurfaceVector::drawVertLine(int x, int y1, int y2, const DrawStyle& c){
248         command_mutex.Lock();
249         unsigned int ref=osd->getStyleRef(c);
250         commands.push_back(SVGCommand::PaintPath(x,y1,1,y2-y1,VertLine,ref));
251         command_mutex.Unlock();
252 }
253
254 void SurfaceVector::drawBitmap(int x, int y, const Bitmap& bm,const DisplayRegion & region)
255 {
256         //this is complicated
257         command_mutex.Lock();
258 /*
259         unsigned int * data=(unsigned int*)malloc(sizeof(unsigned int)*bm.getWidth()*bm.getHeight());
260         for (UINT j = 0; j < bm.getHeight(); ++j){
261            for (UINT i = 0; i < bm.getWidth(); ++i)
262            {
263                    data[i+j*bm.getHeight()]=bm.getColour(i,j);
264            }
265     }*/
266         ImageIndex image=osd->getImagePalette(bm.getWidth(),bm.getHeight(),&(bm.rawData()[0]),
267                         (const unsigned int*)&bm.palette.getColourVector()[0]); // data is freed by the OSD
268         //free(data);
269         float tx=x+region.windowx;
270         float ty=y+region.windowy;
271         float th=bm.getHeight();
272         float tw=bm.getWidth();
273
274         float scalex=720.f/((float) (region.framewidth+1));
275         float scaley=576.f/((float) (region.frameheight+1));
276         tx*=scalex;
277         ty*=scaley;
278         tw*=scalex;
279         th*=scaley;
280         SVGCommand temp=SVGCommand::PaintImage(tx,ty,tw,th,image,0);
281         removeCommands(tx,ty,tw,th);
282         commands.push_back(temp);
283         command_mutex.Unlock();
284 }
285
286 void SurfaceVector::drawPoint(int x, int y, DrawStyle& c, bool fastdraw){
287         if (!fastdraw) command_mutex.Lock();
288         unsigned int ref=osd->getStyleRef(c);
289         commands.push_back(SVGCommand::PaintPath(x,y,1,1,Point,ref));
290         if (!fastdraw)  command_mutex.Unlock();
291 }
292 void SurfaceVector::drawMonoBitmap(UCHAR* base, int dx, int dy, unsigned int height,unsigned int width, DrawStyle& nextColour)
293 {
294         command_mutex.Lock();
295         ImageIndex image=osd->getMonoBitmapRef(base,width,height);
296         unsigned int ref=osd->getStyleRef(nextColour);
297         removeCommands(dx,dy,width,height);
298         commands.push_back(SVGCommand::PaintImage(dx,dy,height,width,image,ref));
299         command_mutex.Unlock();
300 }
301
302
303 int SurfaceVector::removeCommands(float x,float y,float width,float height)
304 {
305         // we iterate through all old commands in order to remove commands hidden by this rectangle
306         list<SVGCommand>::iterator itty=commands.begin();
307         while (itty!=commands.end())
308         {
309                 if ((*itty).Test(x,y,width,height)  && (*itty).instr != DrawClipping) {
310                         //Log::getInstance()->log("OSD", Log::DEBUG, "Remove command %d %g %g %g %g %d %d",(*itty).instr,
311                         //(*itty).x,(*itty).y,(*itty).w,(*itty).h,(*itty).reference,(*itty).target.image);
312                         osd->removeStyleRef((*itty).getRef()); // We remove the Style reference, so that osd can free stuff
313                         ImageIndex ii=(*itty).getImageIndex();
314                         if (ii) osd->removeImageRef(ii);
315                         LoadIndex li=(*itty).getLoadIndex();
316                         if (li) osd->removeLoadIndexRef(li);
317                         itty=commands.erase(itty);
318                 } else {
319                         itty++;
320                 }
321         }
322         return 1;
323
324 }
325
326 int SurfaceVector::updateToScreen(int sx, int sy, int w, int h, int dx, int dy)
327 {
328         // ok this method really works in a pixel oriented way
329         command_mutex.Lock();
330         osd->updateOrAddSurface(this,dx-sx,dy-sy,swidth,sheight,commands);
331         command_mutex.Unlock();
332         return 1;
333 }
334
335
336 /* This is for systems which need a locking of the drawing surface to speed up drawing */
337 void SurfaceVector::startFastDraw() {
338         command_mutex.Lock();
339 }
340 void SurfaceVector::endFastDraw() {
341         command_mutex.Unlock();
342 }
343
344
345 void SurfaceVector::drawTTChar(int ox, int oy,int x, int y, cTeletextChar c)
346 {
347         command_mutex.Lock();
348         list<SVGCommand>::iterator itty=commands.begin();
349         while (itty!=commands.end())
350         {
351                 if ((*itty).TTTest(ox,oy,x,y) ) {
352                         itty=commands.erase(itty);
353                         break;
354                 } else {
355                         itty++;
356                 }
357         }
358         commands.push_back(SVGCommand::PaintTTchar(ox,oy,x,y,c.getInternal()));
359         command_mutex.Unlock();
360 }