]> git.vomp.tv Git - vompclient.git/blob - osdopenvg.cc
Preparations for dynamic mode switching
[vompclient.git] / osdopenvg.cc
1 /*\r
2     Copyright 2004-2005 Chris Tallon, 2006,2011-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 \r
22 #include "osdopenvg.h"\r
23 #include "mtd.h"\r
24 #include "videoomx.h"\r
25 #include "surface.h"\r
26 #include <Magick++.h>\r
27 \r
28 #include "message.h"\r
29 #include "command.h"\r
30 #include "teletxt/txtfont.h"\r
31 \r
32 #include <sys/syscall.h>\r
33 #include <vector>\r
34 #include <math.h>\r
35 \r
36 using namespace Magick;\r
37 \r
38 extern uint8_t font_data[]     asm("_binary_fonts_sourcesans_ttf_start");\r
39 extern uint8_t font_data_end[] asm("_binary_fonts_sourcesans_ttf_end");\r
40 extern uint8_t vdr_data[]     asm("_binary_other_vdrhires_jpg_start");\r
41 extern uint8_t vdr_data_end[] asm("_binary_other_vdrhires_jpg_end");\r
42 extern uint8_t wallpaper_data[]     asm("_binary_other_wallpaper720p_jpg_start");\r
43 extern uint8_t wallpaper_data_end[] asm("_binary_other_wallpaper720p_jpg_end");\r
44 \r
45 \r
46 #define  BACKBUFFER_WIDTH 1280\r
47 #define  BACKBUFFER_HEIGHT 720\r
48 \r
49 \r
50 OsdOpenVG::OsdOpenVG()\r
51 {\r
52   vgmutex.Lock();\r
53   taskmutex.Lock();\r
54   lastrendertime=getTimeMS();\r
55   display_height=0;\r
56   display_width=0;\r
57   mode=0;\r
58   aspect_correction=1.;\r
59 \r
60   freetype_inited=false;\r
61   wait_id=1;\r
62 \r
63 }\r
64 \r
65 OsdOpenVG::~OsdOpenVG()\r
66 {\r
67 \r
68   if (initted)\r
69   {\r
70                 shutdown();\r
71   }\r
72 \r
73   if (freetype_inited) FT_Done_Face(ft_face);\r
74 \r
75   vgmutex.Unlock();\r
76   taskmutex.Unlock();\r
77 }\r
78 \r
79 \r
80 \r
81 int OsdOpenVG::init(void* device)\r
82 {\r
83   if (initted) return 0;\r
84   Video* video = Video::getInstance();\r
85    //window=*((HWND*)device);\r
86 \r
87    // May be this device specific part should go to a device specific child class\r
88 \r
89    //init broadcom chipset (Move to video?)\r
90 \r
91 \r
92    //First get connection to egl\r
93    egl_display=eglGetDisplay(EGL_DEFAULT_DISPLAY);\r
94 \r
95    if (egl_display==EGL_NO_DISPLAY) {\r
96            Log::getInstance()->log("OSD", Log::WARN, "Could not get egl display! %x",eglGetError());\r
97            vgmutex.Unlock();\r
98            return 0;\r
99    }\r
100 \r
101 \r
102 \r
103    if (eglInitialize(egl_display, NULL, NULL)==EGL_FALSE) {\r
104            Log::getInstance()->log("OSD", Log::WARN, "Initialising display failed! %x",eglGetError());\r
105            vgmutex.Unlock();\r
106            return 0;\r
107    }\r
108 \r
109 \r
110    const char *query_str=eglQueryString(egl_display,EGL_CLIENT_APIS);\r
111    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
112    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",eglGetError());\r
113    query_str=eglQueryString(egl_display,EGL_EXTENSIONS);\r
114    if (query_str)    Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
115    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",eglGetError());\r
116 \r
117    if (eglBindAPI(EGL_OPENVG_API)==EGL_FALSE) {\r
118            Log::getInstance()->log("OSD", Log::WARN, "Binding openvg api failed! %x",eglGetError());\r
119            vgmutex.Unlock();\r
120            return 0;\r
121    }\r
122 \r
123    const EGLint attributs[]={\r
124                  EGL_RED_SIZE,8,EGL_GREEN_SIZE, 8,EGL_BLUE_SIZE, 8,EGL_ALPHA_SIZE, 8,\r
125          EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT,\r
126          EGL_CONFORMANT, EGL_OPENVG_BIT,\r
127          EGL_NONE\r
128    }; // Here, we might have to select the resolution!\r
129 \r
130 \r
131    EGLint number;\r
132 \r
133    if (eglChooseConfig(egl_display, attributs, &egl_ourconfig, 1, &number)==EGL_FALSE) {\r
134            Log::getInstance()->log("OSD", Log::WARN, "Choosing egl config failed! %x",eglGetError());\r
135            vgmutex.Unlock();\r
136            return 0;\r
137    }\r
138 \r
139 \r
140 \r
141    egl_context=eglCreateContext(egl_display,egl_ourconfig,NULL,NULL);\r
142    if (egl_context==EGL_NO_CONTEXT) {\r
143            Log::getInstance()->log("OSD", Log::WARN, "Creating egl context failed! %x",eglGetError());\r
144            vgmutex.Unlock();\r
145            return 0;\r
146    }\r
147 \r
148    // warning broadcom specific, get display size!\r
149    display_width=display_height=0;\r
150    if (graphics_get_display_size(0, &display_width, &display_height)<0) {\r
151            Log::getInstance()->log("OSD", Log::WARN, "Getting display size failed! (BCM API) ");\r
152            vgmutex.Unlock();\r
153            return 0;\r
154    }\r
155    Log::getInstance()->log("OSD", Log::NOTICE, "Displaysize is %d x %d ",display_width, display_height);\r
156    VC_RECT_T dst_rect ={0,0,display_width,display_height};\r
157    VC_RECT_T src_rect={0,0,BACKBUFFER_WIDTH <<16,BACKBUFFER_HEIGHT<<16};\r
158   // VC_RECT_T src_rect_bg={0,0,1<<16,1<<16};\r
159  //  VC_RECT_T src_rect_im={0,0,1,1};\r
160 \r
161   /* uint32_t back_image_ptr;\r
162    bcm_backres=vc_dispmanx_resource_create(VC_IMAGE_RGB888,1,1,&back_image_ptr);\r
163    unsigned int color=0x00FF0000;\r
164    vc_dispmanx_resource_write_data(bcm_backres,VC_IMAGE_RGB888,4,&color,&src_rect_im);*/\r
165 \r
166    DISPMANX_UPDATE_HANDLE_T  bcm_update;\r
167    bcm_display=vc_dispmanx_display_open(0);\r
168    bcm_update=vc_dispmanx_update_start(0);\r
169    bcm_element=vc_dispmanx_element_add(bcm_update,bcm_display,\r
170          2,&dst_rect, 0,\r
171          &src_rect,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0);\r
172 \r
173 \r
174  /*  bcm_background=vc_dispmanx_element_add(bcm_update,bcm_display,\r
175             0,&dst_rect,bcm_backres ,\r
176             &src_rect_bg,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0);*/\r
177 \r
178    vc_dispmanx_update_submit_sync(bcm_update);\r
179 \r
180 \r
181 \r
182    static EGL_DISPMANX_WINDOW_T nativewindow;\r
183    nativewindow.element=bcm_element;\r
184    nativewindow.height=BACKBUFFER_HEIGHT;\r
185    nativewindow.width=BACKBUFFER_WIDTH;\r
186 \r
187    egl_surface = eglCreateWindowSurface(egl_display,egl_ourconfig, &nativewindow,NULL );\r
188    if (egl_surface==EGL_NO_SURFACE) {\r
189            Log::getInstance()->log("OSD", Log::WARN, "Creating egl window surface failed!");\r
190            vgmutex.Unlock();\r
191            return 0;\r
192    }\r
193    Log::getInstance()->log("OSD", Log::DEBUG, "Making egl current in1%d",syscall(SYS_gettid));\r
194    if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {\r
195            Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed");\r
196            vgmutex.Unlock();\r
197                    return 0;\r
198    }\r
199    // Test stuff\r
200 \r
201    query_str=(const char*)vgGetString(VG_VERSION) ;\r
202    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
203    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",vgGetError());\r
204 \r
205    query_str=(const char*)vgGetString(VG_VENDOR) ;\r
206    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
207    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",vgGetError());\r
208 \r
209    query_str=(const char*)vgGetString(VG_RENDERER) ;\r
210    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
211    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",vgGetError());\r
212 \r
213    query_str=(const char*)vgGetString(VG_EXTENSIONS) ;\r
214    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
215    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",vgGetError());\r
216 \r
217   aspect_correction= ((float)BACKBUFFER_HEIGHT)/576.f/(((float)BACKBUFFER_WIDTH)/720.f);\r
218   initPaths();\r
219   if (!loadFont()) {\r
220           return 0;\r
221   }\r
222   vgttfont=vgCreateFont(0);\r
223   vgttpaint=vgCreatePaint();\r
224   vgSetParameteri( vgttpaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);\r
225   vgSetColor(vgttpaint,0xffffffff);\r
226 \r
227   eglSwapInterval(egl_display, 1 );\r
228 \r
229   Log::getInstance()->log("OSD", Log::DEBUG, "Making egl current out 1%d",syscall(SYS_gettid));\r
230   eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
231   //Now we will create the Screen\r
232   initted = 1; // must set this here or create surface won't work\r
233 \r
234 \r
235   /*if (((VideoOMX*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init  stuff\r
236           return 0;\r
237   }*/\r
238   InitializeMagick("");\r
239 \r
240   pthread_cond_init(&vgtaskCond, NULL);\r
241   pthread_mutex_init(&vgtaskCondMutex, NULL);\r
242 \r
243   threadStart();\r
244   taskmutex.Unlock();\r
245   vgmutex.Unlock();\r
246 \r
247 \r
248   return 1;\r
249 }\r
250 \r
251 \r
252 void OsdOpenVG::initPaths()\r
253 {\r
254 \r
255 \r
256         VGPath current;\r
257         current=vgCreatePath(VG_PATH_FORMAT_STANDARD,\r
258                         VG_PATH_DATATYPE_F,1.f,0.f,\r
259                         0,0,VG_PATH_CAPABILITY_ALL);\r
260 \r
261         vguLine(current,0.f,0.f,1.f,0.f);\r
262         // HorzLine\r
263         std_paths[HorzLine]=current;\r
264 \r
265         current=vgCreatePath(VG_PATH_FORMAT_STANDARD,\r
266                                 VG_PATH_DATATYPE_F,1.f,0.f,\r
267                                 0,0,VG_PATH_CAPABILITY_ALL);\r
268         vguLine(current,0.f,0.f,0.f,1.f);\r
269         // VertLine\r
270         std_paths[VertLine]=current;\r
271 \r
272         current=vgCreatePath(VG_PATH_FORMAT_STANDARD,\r
273                                 VG_PATH_DATATYPE_F,1.f,0.f,\r
274                                 0,0,VG_PATH_CAPABILITY_ALL);\r
275         //vguRect(current,0.f,0.f,1.f,1.f);\r
276         vguRect(current,0.f,0.f,1.f,1.f);\r
277         // Rectabgle\r
278         std_paths[Rectangle]=current;\r
279 \r
280         current=vgCreatePath(VG_PATH_FORMAT_STANDARD,\r
281                                 VG_PATH_DATATYPE_F,1.f,0.f,\r
282                                 0,0,0);\r
283         vguEllipse(current,0.f,0.f,1.f,1.f);\r
284         // Point\r
285         std_paths[Point]=current;\r
286 \r
287 }\r
288 \r
289 void OsdOpenVG::destroyPaths()\r
290 {\r
291         vgDestroyPath(std_paths[HorzLine]);\r
292         vgDestroyPath(std_paths[VertLine]);\r
293         vgDestroyPath(std_paths[Rectangle]);\r
294         vgDestroyPath(std_paths[Point]);\r
295 \r
296 }\r
297 \r
298 int OsdOpenVG::stopUpdate()\r
299 {\r
300         threadStop();\r
301         processTasks();\r
302         return 1;\r
303 }\r
304 \r
305 \r
306 int OsdOpenVG::shutdown()\r
307 {\r
308   if (!initted) return 0;\r
309 \r
310   initted = 0;\r
311   Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark1");\r
312   threadStop();\r
313   Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark2");\r
314   processTasks();\r
315   Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark3");\r
316 \r
317   taskmutex.Lock();\r
318   vgmutex.Lock();\r
319   //(((VideoOMX*)Video::getInstance())->shutdownUsingOSDObjects());\r
320 \r
321 \r
322 \r
323   vgDestroyFont(vgfont);\r
324   vgDestroyFont(vgttfont);\r
325   vgDestroyPaint(vgttpaint);\r
326   destroyPaths();\r
327   vgClear(0,0,BACKBUFFER_WIDTH,BACKBUFFER_HEIGHT);\r
328   eglSwapBuffers(egl_display, egl_surface);\r
329   Log::getInstance()->log("OSD", Log::DEBUG, "Making egl current out final");\r
330   eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
331   eglDestroySurface(egl_display,egl_surface);\r
332   eglDestroyContext(egl_display,egl_context);\r
333   eglTerminate(egl_display );\r
334 \r
335   DISPMANX_UPDATE_HANDLE_T  bcm_update;\r
336   bcm_update=vc_dispmanx_update_start(0);\r
337 \r
338   vc_dispmanx_element_remove(bcm_update,bcm_element);\r
339 //  vc_dispmanx_element_remove(bcm_update,bcm_background);\r
340   vc_dispmanx_update_submit_sync(bcm_update);\r
341 //  vc_dispmanx_resource_delete(bcm_backres);\r
342   vc_dispmanx_display_close(bcm_display);\r
343 \r
344 \r
345 \r
346   return 1;\r
347 }\r
348 \r
349 \r
350 \r
351 \r
352 void OsdOpenVG::threadMethod()\r
353 {\r
354         // We have to claim the egl context for this thread\r
355 \r
356         if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {\r
357                 Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed in thread %x",eglGetError());\r
358                 return;\r
359         }\r
360         int ts=0;\r
361         while (true)\r
362         {\r
363                 ts=1;\r
364                 unsigned int waittime=1;\r
365 \r
366                 if (initted) {\r
367 \r
368                         long long time1 = getTimeMS();\r
369                         if ((time1 - lastrendertime) > 200) {//5 fps for OSD updates are enough, avoids tearing\r
370                                 InternalRendering();\r
371                                 lastrendertime = getTimeMS();\r
372 \r
373                         }\r
374                         if (processTasks()) ts=0;\r
375                 }\r
376                 threadCheckExit();\r
377                 if (ts!=0) {\r
378                         struct timespec target_time;\r
379                         clock_gettime(CLOCK_REALTIME,&target_time);\r
380                         target_time.tv_nsec+=1000000LL*ts;\r
381                         if (target_time.tv_nsec>999999999) {\r
382                                 target_time.tv_nsec-=1000000000L;\r
383                                 target_time.tv_sec+=1;\r
384                         }\r
385                         threadLock();\r
386                         threadWaitForSignalTimed(&target_time);\r
387                         threadUnlock();\r
388                 }\r
389                 //Sleep(1);\r
390         }\r
391         //eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
392 }\r
393 \r
394 \r
395 void OsdOpenVG::threadPostStopCleanup()\r
396 {\r
397         //Doing nothing\r
398         //goo;\r
399 }\r
400 \r
401 \r
402 \r
403 \r
404 \r
405 \r
406 void OsdOpenVG::InternalRendering(){\r
407         vgmutex.Lock();\r
408     float colclear[]={1.f,1.0f,1.f,1.f};\r
409     vgSetfv(VG_CLEAR_COLOR,4,colclear);\r
410         vgClear(0,0,BACKBUFFER_WIDTH,BACKBUFFER_HEIGHT);\r
411         vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);\r
412 \r
413 \r
414         drawSurfaces(); //iterate through and draws all commands\r
415 \r
416         //Show it to the user!\r
417         eglSwapBuffers(egl_display, egl_surface);\r
418         vgmutex.Unlock();\r
419 \r
420 }\r
421 \r
422 /*font stuff*/\r
423 \r
424 float OsdOpenVG::getFontHeight()\r
425 {\r
426         return font_height; //dummy\r
427 }\r
428 float OsdOpenVG::getCharWidth(wchar_t c)\r
429 {\r
430         unsigned int glyph_index=FT_Get_Char_Index(ft_face,c);\r
431         return font_exp_x[glyph_index];\r
432 }\r
433 \r
434 unsigned int OsdOpenVG::loadTTchar(cTeletextChar c)\r
435 {\r
436         unsigned int glyph_index=c.getGlyphIndex();\r
437         if (tt_font_chars.find(glyph_index)!=tt_font_chars.end())\r
438         {\r
439                 return glyph_index;\r
440         }\r
441 \r
442         unsigned int buffer[10];\r
443         const VGfloat glyphOrigin[] = { 0.f, 0.f };\r
444         const VGfloat escapement[] = { 12.f, 0.f };\r
445         unsigned int * charmap = GetFontChar(c, buffer);\r
446         if (!charmap) { //invalid char\r
447                 return 0;\r
448         }\r
449         for (int i=0;i<10;i++) {\r
450                 buffer[i]=charmap[i]>>4;\r
451         }\r
452 \r
453         VGImage handle = vgCreateImage(\r
454                         VG_A_8,\r
455                         12,\r
456                         10,\r
457                         VG_IMAGE_QUALITY_NONANTIALIASED | VG_IMAGE_QUALITY_FASTER\r
458                                         | VG_IMAGE_QUALITY_BETTER);\r
459         vgImageSubData(handle, buffer, 4, VG_A_1, 0, 0, 12, 10);\r
460         vgSetGlyphToImage(\r
461                         vgttfont,\r
462                         glyph_index,\r
463                         handle, glyphOrigin, escapement);\r
464         vgDestroyImage(handle);\r
465         tt_font_chars[glyph_index]=1;\r
466 \r
467         return glyph_index;\r
468 }\r
469 \r
470 int  OsdOpenVG::loadFont()\r
471 {\r
472         int error;\r
473         float font_size=16.f;\r
474         if (!freetype_inited) {\r
475                 error=FT_Init_FreeType(&ft_library);\r
476                 if (error)\r
477                 {\r
478                         Log::getInstance()->log("OSD", Log::WARN, "Could not load freetype %x",error);\r
479                         return 0;\r
480                 }\r
481 \r
482                 error=FT_New_Memory_Face(ft_library,font_data,font_data_end-font_data,0,&ft_face );\r
483                 if (error) {\r
484                         Log::getInstance()->log("OSD", Log::WARN, "Could not load font face %x",error);\r
485                         return 0;\r
486                 }\r
487                 error=FT_Set_Char_Size(ft_face,0,font_size*64,0,0 /*dpi*/);\r
488                 if (error) {\r
489                         FT_Done_Face(ft_face);\r
490                         Log::getInstance()->log("OSD", Log::WARN, "Could not set  face size %x",error);\r
491                         return 0;\r
492                 }\r
493                 freetype_inited=true;\r
494         }\r
495         vgfont=vgCreateFont(0);\r
496         FT_ULong cur_char;\r
497         FT_UInt glyph;\r
498         font_height=ft_face->size->metrics.height/64.f;\r
499         cur_char = FT_Get_First_Char(ft_face,&glyph);\r
500         vector<VGubyte> segments;\r
501         vector<VGfloat> coord;\r
502         segments.reserve(256);\r
503         coord.reserve(1024);\r
504         //Log::getInstance()->log("OSD", Log::DEBUG, "Create Glyph test %d %x %x %d",cur_char,font_data_end,font_data,glyph);\r
505         while (glyph !=0)\r
506         {\r
507                 error=FT_Load_Glyph(ft_face,glyph,FT_LOAD_DEFAULT);\r
508                 if (error){\r
509                         FT_Done_Face(ft_face);\r
510                         Log::getInstance()->log("OSD", Log::WARN, "Could not load glyph %x",error);\r
511                         return 0;\r
512                 }\r
513                 VGPath path;\r
514                 FT_Outline ot=ft_face->glyph->outline;\r
515                 segments.clear();\r
516                 coord.clear();\r
517 \r
518                 if (ot.n_contours ==0) {\r
519                         path=VG_INVALID_HANDLE;\r
520                 } else {\r
521                         path=vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,\r
522                                         1.0f,0.f,0,0,VG_PATH_CAPABILITY_ALL);\r
523 \r
524                         /* convert glyph */\r
525                         FT_Vector *pt=ot.points;\r
526                         const char *tags=ot.tags;\r
527                         const short* cont=ot.contours;\r
528                         short n_cont=ot.n_contours;\r
529                         short n_point=ot.n_points;\r
530                         short last_cont=0;\r
531                         for (short point=0;n_cont!=0;cont++,n_cont--) {\r
532                                 short next_cont=*cont+1;\r
533                                 bool first=true;\r
534                                 char last_tag=0;\r
535                                 short first_point=point;\r
536                                 //Log::getInstance()->log("OSD", Log::DEBUG, "runs %d",*cont);\r
537                                 for (;point<next_cont;point++) {\r
538                                         char tag=tags[point];\r
539                                         FT_Vector fpoint=pt[point];\r
540                                 //      Log::getInstance()->log("OSD", Log::DEBUG, "tag %d point %d %d: %d %d",tag,fpoint.x,fpoint.y,point,n_point);\r
541                                         if (first) {\r
542                                                 segments.push_back(VG_MOVE_TO);\r
543                                                 first=false;\r
544                                         } else if (tag &0x1) { //on curve\r
545                                                 if (last_tag &0x1) {\r
546                                                         segments.push_back(VG_LINE_TO);\r
547                                                 } else if (last_tag &0x2){\r
548                                                         segments.push_back(VG_CUBIC_TO);\r
549                                                 } else {\r
550                                                         segments.push_back(VG_QUAD_TO);\r
551                                                 }\r
552 \r
553                                         } else {\r
554                                                 if (!(tag &0x2)){\r
555                                                         if (!(last_tag &0x1)) {\r
556                                                                 segments.push_back(VG_QUAD_TO);\r
557                                                                 int coord_size=coord.size();\r
558                                                                 VGfloat x=(coord[coord_size-2]+ ((float)fpoint.x)/64.f)*0.5f*aspect_correction;\r
559                                                                 VGfloat y=(coord[coord_size-1]+(font_size- ((float)fpoint.y)/64.f))*0.5f;\r
560                                                                 coord.push_back(x);\r
561                                                                 coord.push_back(y);\r
562                                                         }\r
563                                                 }\r
564 \r
565 \r
566                                         }\r
567                                         last_tag=tag;\r
568                                         coord.push_back(((float)fpoint.x)*aspect_correction/64.);\r
569                                         coord.push_back(font_size-((float)fpoint.y)/64.);\r
570                                         //Log::getInstance()->log("OSD", Log::DEBUG, "Create APD Glyph coord %d %d %g %g",fpoint.x,fpoint.y,coord[coord.size()-2],coord[coord.size()-1]);\r
571                                 }\r
572                                 if (!(last_tag &0x1)) {\r
573                                         if (last_tag &0x2) {\r
574                                                 segments.push_back(VG_CUBIC_TO);\r
575                                         } else {\r
576                                                 segments.push_back(VG_QUAD_TO);\r
577                                         }\r
578                                         coord.push_back(((float)pt[first_point].x)*aspect_correction/64.);\r
579                                         coord.push_back(font_size-((float)pt[first_point].y)/64.);\r
580                                 }\r
581                                 //segments.push_back(VG_CLOSE_PATH);\r
582 \r
583 \r
584                         }\r
585                         vgAppendPathData(path,segments.size(),&segments[0],&coord[0]);\r
586                         int n=0;\r
587                 /*      for (int m=0;m<segments.size();m++) {\r
588                                 switch (segments[m])\r
589                                 {\r
590                                 case VG_MOVE_TO:\r
591                                         Log::getInstance()->log("OSD", Log::DEBUG, "Move To %g %g",coord[n],coord[n+1]);n+=2; break;\r
592                                 case VG_LINE_TO:\r
593                                         Log::getInstance()->log("OSD", Log::DEBUG, "Line To %g %g",coord[n],coord[n+1]);n+=2; break;\r
594                                 case VG_CUBIC_TO:\r
595                                         Log::getInstance()->log("OSD", Log::DEBUG, "Cubic To %g %g %g %g %g %g",coord[n],coord[n+1],coord[n+2],coord[n+3],coord[n+4],coord[n+5]);n+=6; break;\r
596                                 case VG_QUAD_TO:\r
597                                         Log::getInstance()->log("OSD", Log::DEBUG, "Quad To %g %g %g %g",coord[n],coord[n+1],coord[n+2],coord[n+3]);n+=4; break;\r
598                                 case VG_CLOSE_PATH:\r
599                                         Log::getInstance()->log("OSD", Log::DEBUG, "Close Path"); break;\r
600                                 }\r
601 \r
602                         }*/\r
603                         //vguRect(path,0.f,0.f,1.f,1.f);\r
604                         //Log::getInstance()->log("OSD", Log::DEBUG, "Create APD Glyph %d %x",segments.size(),vgGetError());\r
605                 }\r
606                 VGfloat ori[]={0.f,0.f};\r
607                 VGfloat esp[]={ft_face->glyph->advance.x/64.f*aspect_correction,ft_face->glyph->advance.y/64.f};\r
608                 font_exp_x[glyph]=ft_face->glyph->advance.x/64.f*aspect_correction; //recalculate\r
609 \r
610                 vgSetGlyphToPath(vgfont,glyph,path,VG_FALSE,ori,esp);\r
611                 //Log::getInstance()->log("OSD", Log::DEBUG, "Create Glyph %d %d %x",path,glyph,vgGetError());\r
612                 if (path!=VG_INVALID_HANDLE) {\r
613                         vgDestroyPath(path);\r
614                 }\r
615                 cur_char = FT_Get_Next_Char(ft_face,cur_char,&glyph);\r
616         }\r
617         return 1;\r
618 }\r
619 \r
620 \r
621 void OsdOpenVG::drawSetTrans(SurfaceCommands & sc)\r
622 {\r
623         vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);\r
624         vgLoadIdentity();\r
625         vgScale(((float)BACKBUFFER_WIDTH)/720.f, -((float)BACKBUFFER_HEIGHT)/576.f);\r
626         vgTranslate(0.f+sc.x,-576.f+sc.y);\r
627 \r
628         vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);\r
629         vgLoadIdentity();\r
630     vgScale(((float)BACKBUFFER_WIDTH)/720.f, -((float)BACKBUFFER_HEIGHT)/576.f);\r
631         vgTranslate(0.f+sc.x,-576.f+sc.y);\r
632 \r
633         vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);\r
634         vgLoadIdentity();\r
635         vgScale(((float)BACKBUFFER_WIDTH)/720.f, -((float)BACKBUFFER_HEIGHT)/576.f);\r
636         vgTranslate(0.f+sc.x,-576.f+sc.y);\r
637 \r
638 \r
639 \r
640         //vgTranslate(0.f+sc.x,576.f-sc.y);\r
641         //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Translate %g %g",sc.x,sc.y);\r
642 \r
643 }\r
644 void OsdOpenVG::executeDrawCommand(SVGCommand & command)\r
645 {\r
646 \r
647         VGfloat  save_matrix[9];\r
648         switch (command.instr) {\r
649         case DrawPath: {\r
650         vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);\r
651         //      VGuint rgba;\r
652         //      rgba = vgGetColor((VGPaint) command.reference);\r
653                 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Path %d %x %g %g %g %g",command.reference,command.target.path_index,command.x,command.y,command.w,command.h);\r
654                 //vgSeti(VG_FILL_RULE,);\r
655 \r
656                 vgGetMatrix(save_matrix);\r
657                 vgSetPaint((VGPaint) command.reference,VG_FILL_PATH);\r
658                 vgSetPaint((VGPaint) command.reference,VG_STROKE_PATH);\r
659                 vgTranslate(command.x,command.y);\r
660                 vgScale(command.w,command.h);\r
661                 vgDrawPath(std_paths[command.target.path_index],VG_FILL_PATH);\r
662                 vgLoadMatrix(save_matrix);\r
663         } break;\r
664         case DrawImage: {\r
665             vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);\r
666                 vgGetMatrix(save_matrix);\r
667                 vgTranslate(command.x,command.y);\r
668                 //vgScale(command.w,command.h);\r
669                 if (command.reference) { //special behaviout for bw images they act as a mask on the current paint\r
670                         vgSetPaint((VGPaint) command.reference,VG_FILL_PATH);\r
671                         vgSetPaint((VGPaint) command.reference,VG_STROKE_PATH);\r
672                         vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_STENCIL);\r
673                         vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);\r
674                         vgScale(aspect_correction,1.f);\r
675                 } else {\r
676                         VGfloat imagewidth=vgGetParameteri((VGImage) command.target.image, VG_IMAGE_WIDTH);\r
677                         VGfloat imageheight=vgGetParameteri((VGImage) command.target.image, VG_IMAGE_HEIGHT);\r
678                         //vgScale(720.f/((float)BACKBUFFER_WIDTH), 576.f/((float)BACKBUFFER_HEIGHT));\r
679                         float scalex=command.w/imagewidth;\r
680                         float scaley=command.h/imageheight;\r
681                         //vgScale(command.w/imagewidth,command.h/imageheight);\r
682                         vgScale(scalex,scaley);\r
683                         vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL);\r
684                         //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Image Scale  %g %g %g %g %g %g",command.w,imagewidth,command.h,imageheight,scalex,scaley);\r
685                 }\r
686 \r
687 \r
688                 //vgLoadIdentity();\r
689                 //vgTranslate(200.f,500.f);\r
690                 //vgScale(100.f,100.f);\r
691 \r
692                 vgDrawImage((VGImage) command.target.image);\r
693                 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Image %d %x %g %g %g %g %x",command.reference,command.target.image,command.x,command.y,command.w,command.h,\r
694                 //              vgGetError());\r
695                 if (command.reference) {\r
696                         vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL);\r
697                         vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);\r
698                 }\r
699                 vgLoadMatrix(save_matrix);\r
700         } break;\r
701         case DrawGlyph: {\r
702                 vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);\r
703                 vgGetMatrix(save_matrix);\r
704                 vgSetPaint((VGPaint) command.reference,VG_FILL_PATH);\r
705                 vgSetPaint((VGPaint) command.reference,VG_STROKE_PATH);\r
706                 vgTranslate(command.x,command.y);\r
707                 VGfloat gori[]={0.,0.};\r
708                 vgSetfv(VG_GLYPH_ORIGIN,2,gori);\r
709 \r
710                 unsigned int glyph_index=FT_Get_Char_Index(ft_face,command.target.textchar);\r
711                 vgDrawGlyph(vgfont,glyph_index,VG_FILL_PATH,VG_FALSE);\r
712                 //vgDrawPath(std_paths[Rectangle],VG_FILL_PATH);\r
713         /*      Log::getInstance()->log("OSD", Log::DEBUG, "Draw Glyph %d %c %d %g %g %x",command.reference,command.target.textchar,glyph_index,command.x,command.y,\r
714                                                 vgGetError());*/\r
715                 vgLoadMatrix(save_matrix);\r
716                 vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);\r
717         } break;\r
718         case DrawTTchar:{\r
719                 cTeletextChar tchar;\r
720                 tchar.setInternal(command.target.ttchar);\r
721                 vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);\r
722                 vgGetMatrix(save_matrix);\r
723                 enumTeletextColor ttforegcolour=tchar.GetFGColor();\r
724                 enumTeletextColor ttbackgcolour=tchar.GetBGColor();\r
725             if (tchar.GetBoxedOut()) {\r
726                 ttforegcolour=ttcTransparent;\r
727                 ttbackgcolour=ttcTransparent;\r
728             }\r
729             vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_STENCIL);\r
730             vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);\r
731 \r
732 \r
733                 vgTranslate(command.x+command.w*11.85f*1.4f,command.y+command.h*19.75f);\r
734                 VGfloat gori[]={0.,0.};\r
735                 vgSetfv(VG_GLYPH_ORIGIN,2,gori);\r
736 \r
737                 vgScale(-1.4f,2.f);\r
738                 unsigned int color=Surface::enumTeletextColorToCoulour(ttbackgcolour).rgba();\r
739                 color=color<<8 | (color &0xff000000)>>24;\r
740                 vgSetColor(vgttpaint,color);\r
741                 vgSetPaint((VGPaint) vgttpaint,VG_FILL_PATH);\r
742                 vgSetPaint((VGPaint) vgttpaint,VG_STROKE_PATH);\r
743                 cTeletextChar filled;\r
744                 filled.setInternal(0x187f);\r
745                 unsigned int glyph_index=loadTTchar(filled);\r
746                 vgDrawGlyph(vgttfont,glyph_index,VG_FILL_PATH,VG_FALSE);\r
747 \r
748                 color=Surface::enumTeletextColorToCoulour(ttforegcolour).rgba();\r
749                 color=color<<8 | (color &0xff000000)>>24;\r
750                 vgSetColor(vgttpaint,color);\r
751                 vgSetPaint((VGPaint) vgttpaint,VG_FILL_PATH);\r
752                 vgSetPaint((VGPaint) vgttpaint,VG_STROKE_PATH);\r
753                 glyph_index=loadTTchar(tchar);\r
754                 vgDrawGlyph(vgttfont,glyph_index,VG_FILL_PATH,VG_FALSE);\r
755 \r
756                 /*      Log::getInstance()->log("OSD", Log::DEBUG, "Draw TTchar %x %x %x %x",glyph_index,ttforegcolour,Surface::enumTeletextColorToCoulour(ttforegcolour).rgba(),\r
757                                         vgGetColor(vgttpaint));*/\r
758 \r
759 \r
760                 vgLoadMatrix(save_matrix);\r
761                 vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);\r
762                 vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL);\r
763                 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);\r
764 \r
765         }break;\r
766         }\r
767 }\r
768 \r
769 unsigned int OsdOpenVG::handleTask(OpenVGCommand& command)\r
770 {\r
771         switch (command.task){\r
772         case OVGdestroyImageRef: {\r
773                 vgDestroyImage((VGImage)command.param1);\r
774                 return 0;\r
775         } break;\r
776         case OVGdestroyPaint: {\r
777                 Log::getInstance()->log("OSD", Log::DEBUG, "Draw Paint Destroy %d ",command.param1);\r
778                 vgDestroyPaint((VGPaint)command.param1);\r
779                 return 0;\r
780         } break;\r
781         case OVGcreateImagePalette: {\r
782                 VGImage input=vgCreateImage(VG_A_8,command.param1, command.param2,\r
783                                 VG_IMAGE_QUALITY_NONANTIALIASED|\r
784                                 VG_IMAGE_QUALITY_FASTER|VG_IMAGE_QUALITY_BETTER);\r
785                 vgImageSubData(input,command.data,command.param1,\r
786                                                         VG_A_8,0,0,command.param1, command.param2); // upload palettized image data\r
787                 VGImage handle=vgCreateImage(VG_sRGBA_8888,command.param1, command.param2,\r
788                                                 VG_IMAGE_QUALITY_NONANTIALIASED|\r
789                                                 VG_IMAGE_QUALITY_FASTER|VG_IMAGE_QUALITY_BETTER);\r
790                 VGuint *palette=(VGuint*)malloc(256*sizeof(VGuint));\r
791                 VGuint *in_palette=(VGuint*)command.data2;\r
792                 for (int i=0;i<256;i++) {\r
793                         VGuint color=in_palette[i];\r
794                         palette[i]=color<<8 | (color &0xff000000)>>24;\r
795                 }\r
796 \r
797                 vgLookupSingle(handle,input,palette,VG_ALPHA,VG_FALSE,VG_FALSE);\r
798                 free(palette);\r
799                 vgDestroyImage(input);\r
800 \r
801                 return handle;\r
802         } break;\r
803         case OVGcreateMonoBitmap: {\r
804                 VGImage handle=vgCreateImage(VG_A_1,command.param1, command.param2,\r
805                                         VG_IMAGE_QUALITY_NONANTIALIASED|\r
806                                         VG_IMAGE_QUALITY_FASTER|VG_IMAGE_QUALITY_BETTER);\r
807                 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create mono  %d %d %x %d",command.param1,command.param2,vgGetError(),handle);\r
808                 unsigned int buffer_len=(command.param1*command.param2)>>3;\r
809                 unsigned char * buffer=(unsigned char*)malloc(buffer_len);\r
810                 unsigned char * r_buffer1=buffer;\r
811                 const unsigned char * r_buffer2=(const unsigned char *)command.data;\r
812                 unsigned char *buffer_end=buffer+buffer_len;\r
813                 while (r_buffer1!=buffer_end) {\r
814                         unsigned char byte=*r_buffer2;\r
815                         *r_buffer1=((byte * 0x0802LU & 0x22110LU) | (byte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;\r
816                         r_buffer1++;r_buffer2++;\r
817                 }\r
818 \r
819 \r
820                 vgImageSubData(handle,buffer,command.param1>>3,\r
821                                         VG_A_1,0,0,command.param1, command.param2);\r
822                 free(buffer);\r
823         //      Log::getInstance()->log("OSD", Log::DEBUG, "Draw create mono2  %d %d %x %d",command.param1,command.param2,vgGetError(),handle);\r
824                 return handle;\r
825         } break;\r
826         case OVGcreateImageFile: {\r
827                 VGImage handle;\r
828                 try{\r
829                         Image *imagefile=(Image*)command.data;\r
830                         Blob imageblob;\r
831                         imagefile->write(&imageblob,"RGBA");\r
832 \r
833 \r
834                         handle=vgCreateImage(VG_sXBGR_8888,imagefile->columns(),imagefile->rows(),\r
835                                         VG_IMAGE_QUALITY_NONANTIALIASED|\r
836                                         VG_IMAGE_QUALITY_FASTER|VG_IMAGE_QUALITY_BETTER);\r
837                 //      Log::getInstance()->log("OSD", Log::DEBUG, "Draw create image details  %d %d %x mark1",imagefile->columns(),imagefile->rows(),*(unsigned int*)imageblob.data());\r
838                         vgImageSubData(handle,imageblob.data(),imagefile->columns()*4,\r
839                                         VG_sXBGR_8888,0,0,imagefile->columns(),imagefile->rows());\r
840                 //      Log::getInstance()->log("OSD", Log::DEBUG, "Draw create image details  %d %d %x mark2",imagefile->columns(),imagefile->rows(),*(unsigned int*)imageblob.data());\r
841                         delete imagefile;\r
842                 }catch( Exception &error_ )\r
843                 {\r
844                         Log::getInstance()->log("OSD", Log::DEBUG, "Libmagick hT: %s",error_.what());\r
845 \r
846                         return 0;\r
847                 }\r
848 \r
849                 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create file  %d %d %x %d",command.param1,command.param2,vgGetError(),handle);\r
850                 return handle;\r
851         } break;\r
852         case OVGcreateColorRef :{\r
853                 VGPaint handle;\r
854                 handle=vgCreatePaint();\r
855                 vgSetParameteri(handle, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);\r
856                 vgSetColor(handle,command.param1);\r
857                 VGuint rgba;\r
858                 rgba = vgGetColor((VGPaint)handle);\r
859                 Log::getInstance()->log("OSD", Log::DEBUG, "Draw Paint %d %x %x",handle,command.param1,rgba);\r
860                 return handle;\r
861         } break;\r
862         case OVGimageUploadLine: {\r
863                 vgImageSubData((VGImage)command.param1,command.data,0,VG_sARGB_8888,0,command.param2,command.param3,1);\r
864                 return 0;\r
865         } break;\r
866 \r
867         }\r
868 }\r
869 \r
870 bool OsdOpenVG::processTasks()\r
871 {\r
872         bool worked=false;\r
873         taskmutex.Lock();\r
874         vgmutex.Lock();\r
875         while (vgcommands.size()>0)\r
876         {\r
877                 OpenVGCommand &comm=vgcommands.front();\r
878                 OpenVGResponse resp;\r
879                 resp.result=handleTask(comm);\r
880                 resp.id=comm.id;\r
881                 if (comm.id) {\r
882                         vgresponses.push_back(resp);\r
883                 }\r
884                 vgcommands.pop_front();\r
885                 taskmutex.Unlock();\r
886                 vgmutex.Unlock();\r
887                 //threadCheckExit();\r
888                 pthread_mutex_lock(&vgtaskCondMutex);\r
889                 pthread_cond_signal(&vgtaskCond);\r
890                 pthread_mutex_unlock(&vgtaskCondMutex);\r
891                 taskmutex.Lock();\r
892                 vgmutex.Lock();\r
893                 worked=true;\r
894         }\r
895         taskmutex.Unlock();\r
896         vgmutex.Unlock();\r
897 \r
898         return worked;\r
899 }\r
900 \r
901 bool OsdOpenVG::haveOpenVGResponse(unsigned int id,unsigned int * resp)\r
902 {\r
903         taskmutex.Lock();\r
904         if (vgresponses.size()>0)\r
905         {\r
906                 deque<OpenVGResponse>::iterator itty=vgresponses.begin();\r
907                 while (itty!=vgresponses.end())\r
908                 {\r
909                         if ((*itty).id==id) {\r
910                                 *resp=(*itty).result;\r
911                                 taskmutex.Unlock();\r
912                                 return true;\r
913                         }\r
914                         itty++;\r
915                 }\r
916         }\r
917         taskmutex.Unlock();\r
918         return false;\r
919 }\r
920 \r
921 \r
922 unsigned int  OsdOpenVG::putOpenVGCommand(OpenVGCommand& comm,bool wait)\r
923 {\r
924         taskmutex.Lock();\r
925         if (wait){\r
926                 comm.id=wait_id;\r
927                 wait_id++;\r
928         } else {\r
929                 comm.id=0; // we are not waiting\r
930         }\r
931         vgcommands.push_back(comm);\r
932         taskmutex.Unlock();\r
933         threadSignal();\r
934         while (wait) {\r
935                 unsigned int resp;\r
936                 if (!haveOpenVGResponse(comm.id,&resp)) {\r
937                         struct timespec target_time;\r
938                         clock_gettime(CLOCK_REALTIME,&target_time);\r
939                         target_time.tv_nsec+=1000000LL*100;\r
940                         if (target_time.tv_nsec>999999999) {\r
941                                         target_time.tv_nsec-=1000000000L;\r
942                                         target_time.tv_sec+=1;\r
943                         }\r
944                         pthread_mutex_lock(&vgtaskCondMutex);\r
945                         pthread_cond_timedwait(&vgtaskCond, &vgtaskCondMutex,&target_time);\r
946                         pthread_mutex_unlock(&vgtaskCondMutex);\r
947                 } else {\r
948                         return resp;\r
949                 }\r
950         }\r
951         return 0;\r
952 }\r
953 \r
954 void OsdOpenVG::imageUploadLine(ImageIndex index,unsigned int j,unsigned int width,void *data)\r
955 {\r
956         vgImageSubData((VGImage)index,data,0,VG_sARGB_8888,0,j,width,1);\r
957 \r
958         struct OpenVGCommand comm;\r
959         comm.task=OVGimageUploadLine;\r
960         comm.param1=index;\r
961         comm.param2=j;\r
962         comm.param3=width;\r
963         comm.data=data;\r
964         putOpenVGCommand(comm,true);\r
965 }\r
966 \r
967 void OsdOpenVG::destroyImageRef(ImageIndex index)\r
968 {\r
969         struct OpenVGCommand comm;\r
970         comm.task=OVGdestroyImageRef;\r
971         comm.param1=index;\r
972         putOpenVGCommand(comm,false);\r
973 }\r
974 \r
975 ImageIndex OsdOpenVG::createJpeg(const char* fileName, int *width,int *height)\r
976 {\r
977         Image* magicimage=NULL;\r
978         bool mem=false;\r
979         struct OpenVGCommand comm;\r
980         comm.task=OVGcreateImageFile;\r
981 \r
982         try{\r
983                 // Now figure out, if it is a special case\r
984                 if (strcmp(fileName,"/vdr.jpg")==0) {\r
985                         magicimage=new Image(Blob(vdr_data,vdr_data_end-vdr_data));\r
986                         *height=100; // this is faked so that the system does use the old coordinate system\r
987                         *width=ceil(190.f*aspect_correction);\r
988                         Log::getInstance()->log("OSD", Log::DEBUG, "LoadIm vdr.jpg");\r
989                 } else if (strcmp(fileName,"/wallpaperPAL.jpg")==0) {\r
990                         magicimage=new Image(Blob(wallpaper_data,wallpaper_data_end-wallpaper_data));\r
991                         *width=720; // this is faked so that the system does use the old coordinate system\r
992                         *height=576;\r
993                         Log::getInstance()->log("OSD", Log::DEBUG, "LoadIm wallpaperPAL.jpg");\r
994                 } else {\r
995                         magicimage=new Image();\r
996                         magicimage->read(fileName);\r
997                         Log::getInstance()->log("OSD", Log::DEBUG, "LoadIm file: %s",fileName);\r
998                         *width=ceil(magicimage->baseColumns()*aspect_correction); // this is faked so that the system does use the old coordinate system\r
999                         *height=magicimage->baseRows();\r
1000                 }\r
1001 \r
1002         }catch( Exception &error_ )\r
1003         {\r
1004                 Log::getInstance()->log("OSD", Log::DEBUG, "Libmagick: %s",error_.what());\r
1005 \r
1006                 return 0;\r
1007         }\r
1008         comm.data=magicimage;\r
1009         return putOpenVGCommand(comm,true);\r
1010 }\r
1011 \r
1012 ImageIndex OsdOpenVG::createMonoBitmap(void *base,int width,int height)\r
1013 {\r
1014         struct OpenVGCommand comm;\r
1015         comm.task=OVGcreateMonoBitmap;\r
1016         comm.param1=width;\r
1017         comm.param2=height;\r
1018         comm.data=base;\r
1019         return putOpenVGCommand(comm,true);\r
1020 }\r
1021 \r
1022 ImageIndex OsdOpenVG::createImagePalette(int width,int height,const unsigned char *image_data,const unsigned int*palette_data)\r
1023 {\r
1024     struct OpenVGCommand comm;\r
1025     comm.task=OVGcreateImagePalette;\r
1026     comm.param1=width;\r
1027     comm.param2=height;\r
1028     comm.data=image_data;\r
1029     comm.data2=palette_data;\r
1030     return putOpenVGCommand(comm,true);\r
1031 }\r
1032 \r
1033 void OsdOpenVG::destroyStyleRef(unsigned int index)\r
1034 {\r
1035         struct OpenVGCommand comm;\r
1036         comm.task=OVGdestroyPaint;\r
1037         comm.param1=index;\r
1038         putOpenVGCommand(comm,false);\r
1039 }\r
1040 \r
1041 unsigned int OsdOpenVG::createStyleRef(const DrawStyle &c)\r
1042 {\r
1043         unsigned int col=c.rgba();\r
1044         struct OpenVGCommand comm;\r
1045         comm.task=OVGcreateColorRef;\r
1046         comm.param1=col<<8 | (col &0xff000000)>>24;\r
1047         comm.data=&c;\r
1048         return putOpenVGCommand(comm,true);\r
1049 }\r
1050 \r
1051 unsigned int OsdOpenVG::createColorRef(const Colour &c)\r
1052 {\r
1053         unsigned int col=c.rgba();\r
1054         struct OpenVGCommand comm;\r
1055         comm.task=OVGcreateColorRef;\r
1056         comm.param1=col<<8 | (col &0xff000000)>>24;\r
1057         comm.data=&c;\r
1058         return putOpenVGCommand(comm,true);\r
1059 }\r
1060 \r
1061 \r