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