]> git.vomp.tv Git - vompclient.git/blob - osdvector.cc
Preparations for dynamic mode switching
[vompclient.git] / osdvector.cc
1 /*\r
2     Copyright 2012 Marten Richter\r
3 \r
4     This file is part of VOMP.\r
5 \r
6     VOMP is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     VOMP is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with VOMP; if not, write to the Free Software\r
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
19 */\r
20 \r
21 #include "osdvector.h"\r
22 #include "surfacevector.h"\r
23 \r
24 OsdVector::OsdVector()\r
25 {\r
26         setlocale(LC_CTYPE,"C.UTF-8");\r
27 }\r
28 \r
29 OsdVector::~OsdVector()\r
30 {\r
31 \r
32 }\r
33 \r
34 \r
35 int OsdVector::getFD()\r
36 {\r
37         return 0;\r
38 }\r
39 \r
40 void OsdVector::screenShot(const char* fileName)\r
41 {\r
42         //Do nothing,\r
43 }\r
44 \r
45 Surface * OsdVector::createNewSurface()\r
46 {\r
47         return new SurfaceVector(this);\r
48 }\r
49 \r
50 void OsdVector::BeginPainting()\r
51 {\r
52         surfaces_mutex.Lock();\r
53 }\r
54 void OsdVector::EndPainting()\r
55 {\r
56         surfaces_mutex.Unlock();\r
57 }\r
58 \r
59 void OsdVector::Blank()\r
60 {\r
61         // do nothing? remove this one?\r
62 }\r
63 \r
64 int OsdVector::restore()\r
65 {\r
66         // First clear the contents of all registered surfaces\r
67         surfaces_mutex.Lock();\r
68 \r
69         //Now go through all surfaces and draw them\r
70         list<SurfaceCommands>::iterator curdraw=scommands.begin();\r
71         while (curdraw!=scommands.end()) {\r
72                 (*curdraw).commands.clear();\r
73                 curdraw++;\r
74         }\r
75         //also clear all handles, they are now invalid, no need to release them\r
76         images_ref.clear();;\r
77         monobitmaps.clear();\r
78         jpegs.clear();\r
79         styles.clear();\r
80         styles_ref.clear();\r
81 \r
82         surfaces_mutex.Unlock();\r
83         return 1;\r
84 }\r
85 \r
86 void OsdVector::drawSurfaces()\r
87 {\r
88         surfaces_mutex.Lock();\r
89         list<SurfaceCommands*> todraw; //First figure out if a surfaces is below another surface\r
90         list<SurfaceCommands>::iterator itty1=scommands.begin();\r
91         while (itty1!=scommands.end()) {\r
92                 list<SurfaceCommands>::iterator itty2=itty1;\r
93                 itty2++;\r
94                 bool hidden=false;\r
95                 while (itty2!=scommands.end()) {\r
96                         SurfaceCommands & ref1=*itty1;\r
97                         SurfaceCommands & ref2=*itty2;\r
98                         if (ref1.x>=ref2.x && ref1.y>=ref2.y\r
99                                         && (ref1.x+ref1.w) <= (ref2.x+ref2.w)\r
100                                         && (ref1.y+ref1.h) <= (ref2.y+ref2.h) ) {\r
101                                 hidden=true;\r
102                                 break;\r
103                         }\r
104                         itty2++;\r
105                 }\r
106                 if (!hidden) { // we are not hidden, perfect\r
107                         todraw.push_back(&(*itty1));\r
108                 }\r
109                 itty1++;\r
110         }\r
111         //Now go through all surfaces and draw them\r
112         list<SurfaceCommands*>::iterator curdraw=todraw.begin();\r
113         while (curdraw!=todraw.end()) {\r
114                 drawSetTrans(*(*curdraw));\r
115                 list<SVGCommand>::iterator commands=(*(*curdraw)).commands.begin();\r
116                 list<SVGCommand>::iterator end=(*(*curdraw)).commands.end();\r
117                 while (commands!=end) {\r
118                         executeDrawCommand(*commands);\r
119                         commands++;\r
120                 }\r
121                 curdraw++;\r
122         }\r
123 \r
124         surfaces_mutex.Unlock();\r
125 }\r
126 \r
127 \r
128 void OsdVector::updateOrAddSurface(const SurfaceVector *surf,float x,float y,float height,float width,\r
129                         list<SVGCommand>& commands)\r
130 {\r
131         surfaces_mutex.Lock();\r
132         //First determine it is already in our system\r
133         list<SurfaceCommands>::iterator itty=scommands.begin();\r
134         while (itty!=scommands.end()) {\r
135                 if ((*itty).surf==surf) {\r
136                         //decrease the references\r
137                         dereferenceSVGCommand((*itty).commands);\r
138                         break;\r
139                 }\r
140                 itty++;\r
141         }\r
142         // if not insert it\r
143         if (itty==scommands.end()) {\r
144                 SurfaceCommands new_sc;\r
145                 new_sc.surf=surf;\r
146                 new_sc.x=x;\r
147                 new_sc.y=y;\r
148                 new_sc.w=width;\r
149                 new_sc.h=height;\r
150                 itty=scommands.insert(itty,new_sc);\r
151         }\r
152         // then clear and copy\r
153         (*itty).commands.clear();\r
154         (*itty).commands=commands;\r
155         //increase the references\r
156         list<SVGCommand>::iterator sitty=(*itty).commands.begin();\r
157         while (sitty!=(*itty).commands.end())\r
158         {\r
159                 incStyleRef((*sitty).getRef());\r
160                 ImageIndex ii=(*sitty).getImageIndex();\r
161                 if (ii) incImageRef(ii);\r
162                 sitty++;\r
163         }\r
164         cleanupOrphanedRefs();\r
165 \r
166         surfaces_mutex.Unlock();\r
167 }\r
168 \r
169 void OsdVector::removeSurface(const SurfaceVector *surf)\r
170 {\r
171         surfaces_mutex.Lock();\r
172         //First determine it is already in our system\r
173         list<SurfaceCommands>::iterator itty=scommands.begin();\r
174         while (itty!=scommands.end()) {\r
175                 if ((*itty).surf==surf) {\r
176                         dereferenceSVGCommand((*itty).commands);\r
177                         (*itty).commands.clear();\r
178                         scommands.erase(itty);\r
179                         break;\r
180                 }\r
181                 itty++;\r
182         }\r
183         surfaces_mutex.Unlock();\r
184 \r
185 }\r
186 \r
187 void OsdVector::dereferenceSVGCommand(list<SVGCommand>& commands )\r
188 {\r
189 \r
190         list<SVGCommand>::iterator sitty = commands.begin();\r
191         while (sitty != commands.end()) {\r
192                 removeStyleRef((*sitty).getRef());\r
193                 ImageIndex ii = (*sitty).getImageIndex();\r
194                 if (ii) removeImageRef(ii);\r
195                 sitty++;\r
196         }\r
197 }\r
198 \r
199 void OsdVector::referenceSVGCommand(list<SVGCommand>& commands )\r
200 {\r
201         list<SVGCommand>::iterator sitty=commands.begin();\r
202         while (sitty!=commands.end())\r
203         {\r
204                 incStyleRef((*sitty).getRef());\r
205                 ImageIndex ii=(*sitty).getImageIndex();\r
206                 if (ii) incImageRef(ii);\r
207                 sitty++;\r
208         }\r
209 }\r
210 \r
211 void OsdVector::incImageRef(ImageIndex index)\r
212 {\r
213         if (images_ref.find(index)==images_ref.end()) {\r
214                 images_ref[index]=1;\r
215         } else {\r
216                 images_ref[index]++;\r
217         }\r
218 }\r
219 \r
220 void OsdVector::removeImageRef(const ImageIndex ref)\r
221 {\r
222         images_ref[ref]--;\r
223 }\r
224 \r
225 void OsdVector::cleanupOrphanedRefs()\r
226 { // Do some garbage collection\r
227 \r
228         map<void *,ImageIndex>::iterator mitty=monobitmaps.begin();\r
229         while (mitty!=monobitmaps.end()) {\r
230                 map<ImageIndex,unsigned int>::iterator curitty=images_ref.find((*mitty).second);\r
231                 int count=(*curitty).second;\r
232                 if (count==0) {\r
233                         ImageIndex ref=(*curitty).first;\r
234                         monobitmaps.erase(mitty++);\r
235                         images_ref.erase(curitty++);\r
236                         destroyImageRef(ref);\r
237                 } else ++mitty;\r
238         }\r
239 \r
240         map<string,ImageIndex>::iterator jitty=jpegs.begin();\r
241         while (jitty!=jpegs.end()) {\r
242                 map<ImageIndex,unsigned int>::iterator curitty=images_ref.find((*jitty).second);\r
243                 int count=(*curitty).second;\r
244                 if (count==0) {\r
245                         ImageIndex ref=(*curitty).first;\r
246                         jpegs.erase(jitty++);\r
247                         images_ref.erase(curitty++);\r
248                         destroyImageRef(ref);\r
249                 } else ++jitty;\r
250         }\r
251 \r
252 \r
253         map<pair<Colour*,unsigned int>,unsigned int>::iterator sitty=styles.begin();\r
254         while (sitty!=styles.end()) {\r
255                 map<unsigned int,unsigned int>::iterator curitty=styles_ref.find((*sitty).second);\r
256                 int count=(*curitty).second;\r
257                 if (count==0) {\r
258                         unsigned int ref=(*curitty).first;\r
259                         styles.erase(sitty++);\r
260                         styles_ref.erase(curitty++);\r
261                         destroyStyleRef(ref);\r
262 \r
263                 } else ++sitty;\r
264 \r
265         }\r
266 }\r
267 \r
268 \r
269 unsigned int OsdVector::getImageRef(ImageIndex index)\r
270 {\r
271         if (images_ref.find(index)==images_ref.end()) {\r
272                 return -1;\r
273         } else {\r
274                 return images_ref[index];\r
275         }\r
276 }\r
277 \r
278 void OsdVector::incStyleRef(unsigned int index)\r
279 {\r
280         if (styles_ref.find(index)==styles_ref.end()) {\r
281                 styles_ref[index]=1;\r
282         } else {\r
283                 styles_ref[index]++;\r
284         }\r
285 }\r
286 \r
287 void OsdVector::removeStyleRef(unsigned int index)\r
288 {\r
289         styles_ref[index]--;\r
290 }\r
291 \r
292 unsigned int OsdVector::getStyleRef(const DrawStyle &c)\r
293 {\r
294         unsigned int style_handle=0;\r
295         if (styles.find(pair<Colour*,unsigned int>((Colour*)&c,c.rgba()))==styles.end())\r
296         {\r
297                 style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())]=createStyleRef(c);\r
298         } else {\r
299                 style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())];\r
300                 //Now check if the handle is valid\r
301                 if (styles_ref.find(style_handle)==styles_ref.end()) {\r
302                         //invalid handle recreate\r
303                         style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())]=createStyleRef(c);\r
304                 }\r
305         }\r
306         incStyleRef(style_handle);\r
307         return style_handle;\r
308 }\r
309 \r
310 unsigned int OsdVector::getColorRef(const Colour &c)\r
311 {\r
312         unsigned int style_handle=0;\r
313         if (styles.find(pair<Colour*,unsigned int>((Colour*)&c,c.rgba()))==styles.end())\r
314         {\r
315                 style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())]=createColorRef(c);\r
316         } else {\r
317                 style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())];\r
318                 if (styles_ref.find(style_handle)==styles_ref.end()) {\r
319                         //invalid handle recreate\r
320                         style_handle=styles[pair<Colour*,unsigned int>((Colour*)&c,c.rgba())]=createColorRef(c);\r
321                 }\r
322         }\r
323         incStyleRef(style_handle);\r
324         return style_handle;\r
325 }\r
326 \r
327 unsigned int OsdVector::getStyleRef(unsigned int index)\r
328 {\r
329         if (styles_ref.find(index)==styles_ref.end()) {\r
330                 return -1;\r
331         } else {\r
332                 return styles_ref[index];\r
333         }\r
334 }\r
335 \r
336 ImageIndex OsdVector::getJpegRef(const char* fileName, int *width,int *height)\r
337 {\r
338         ImageIndex image_handle=0;\r
339         if (jpegs.find(fileName)==jpegs.end())\r
340         {\r
341                 image_handle=jpegs[fileName]=createJpeg(fileName,width,height);\r
342         } else {\r
343                 image_handle=jpegs[fileName];\r
344                 *width=0;\r
345                 *height=0;\r
346                 if (images_ref.find(image_handle)==images_ref.end()) {\r
347                         //invalid handle recreate\r
348                         image_handle=jpegs[fileName]=createJpeg(fileName,width,height);\r
349                 }\r
350         }\r
351         incImageRef(image_handle);\r
352         return image_handle;\r
353 }\r
354 \r
355 ImageIndex OsdVector::getMonoBitmapRef(void *base,int width,int height)\r
356 {\r
357         ImageIndex image_handle;\r
358         if (monobitmaps.find(base)==monobitmaps.end())\r
359         {\r
360                 image_handle=monobitmaps[base]=createMonoBitmap(base,width,height);\r
361         } else {\r
362                 image_handle=monobitmaps[base];\r
363                 if (images_ref.find(image_handle)==images_ref.end()) {\r
364                         //invalid handle recreate\r
365                         image_handle=monobitmaps[base]=createMonoBitmap(base,width,height);\r
366                 }\r
367         }\r
368         incImageRef(image_handle);\r
369         return image_handle;\r
370 }\r
371 \r
372 ImageIndex  OsdVector::getImagePalette(int width,int height,const unsigned char *image_data,const unsigned int*palette_data)\r
373 {\r
374         ImageIndex image_handle;\r
375         image_handle=createImagePalette(width,height,image_data,palette_data);\r
376         incImageRef(image_handle);\r
377         return image_handle;\r
378 }\r