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