]> git.vomp.tv Git - vompclient.git/blob - osdwinvector.cc
Windows fixes
[vompclient.git] / osdwinvector.cc
1 /*
2     Copyright 2014 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
21 #include "osdwinvector.h"
22 #include "videowin.h"
23 #include "surfacewin.h"
24
25
26 #include "message.h"
27 #include "messagequeue.h"
28
29 #include "teletxt/txtfont.h"
30
31 #include <wincodec.h>
32
33 #define  OSD_BUFFER_WIDTH 1280
34 #define  OSD_BUFFER_HEIGHT 720
35
36 #include "staticartwork.h"
37
38 #define EXTERNALPICTURE(name, fname, fileextension)  #name, 
39
40 char *ext_pict_name[] {
41         "None",
42         EXTERNAL_PICTS
43 };
44
45 #undef EXTERNALPICTURE
46
47
48 class WICPictDecoder : public OsdVector::PictureDecoder {
49 public:
50         WICPictDecoder(OsdVector::PictureReader* treader, OsdWinVector *posd);
51         virtual ~WICPictDecoder();
52
53         unsigned char *decodePicture(LoadIndex index, unsigned char * buffer, unsigned int length, bool freemem);
54
55         bool getDecodedPicture(struct OsdVector::PictureInfo& pict_inf);
56
57         void freeReference(void * ref);
58
59 protected:
60         OsdVector::PictureInfo pictInf;
61         bool pictInfValid;
62         IWICImagingFactory *wicfactory;
63         OsdWinVector * osd;
64 };
65
66 WICPictDecoder::WICPictDecoder(OsdVector::PictureReader* treader, OsdWinVector *posd) : OsdVector::PictureDecoder(treader)
67 {
68         pictInfValid = false; 
69         osd = posd;
70         HRESULT hres = CoCreateInstance(CLSID_WICImagingFactory,
71                 NULL,CLSCTX_INPROC_SERVER,
72                 IID_IWICImagingFactory, (void**)&wicfactory);
73
74
75 }
76
77 WICPictDecoder::~WICPictDecoder()
78 {
79         wicfactory->Release();
80 }
81
82 unsigned char * WICPictDecoder::decodePicture(LoadIndex index, unsigned char * buffer, unsigned int length, bool freemem)
83 {
84         if (pictInfValid) return buffer; // does support only one image at a Time;
85         
86         IWICStream * stream = NULL;
87         IWICBitmapDecoder *decoder = NULL;
88         IWICBitmapFrameDecode *source = NULL;
89         IWICFormatConverter *converter = NULL;
90
91         HRESULT hres;
92
93         hres = wicfactory->CreateStream(&stream);
94
95         if (hres != S_OK)
96         {
97
98                 Log::getInstance()->log("WICDecoder", Log::DEBUG, "Could not create stream %d", hres);
99                 return buffer;
100         }
101         hres = stream->InitializeFromMemory(buffer, length);
102
103         if (hres != S_OK)
104         {
105                 Log::getInstance()->log("WICDecoder", Log::DEBUG, "Could not initialize from memory %d", hres);
106                 stream->Release();
107                 return buffer;
108         }
109
110
111         hres = wicfactory->CreateDecoderFromStream(stream, NULL, WICDecodeMetadataCacheOnLoad, &decoder);
112         if (hres != S_OK)
113         {
114
115                 Log::getInstance()->log("WICDecoder", Log::DEBUG, "Could not create decoder %d", hres);
116                 stream->Release();
117                 return buffer;
118         }
119
120         hres = decoder->GetFrame(0, &source);
121         if (hres != S_OK)
122         {
123
124                 Log::getInstance()->log("WICDecoder", Log::DEBUG, "Could not get source %d", hres);
125                 decoder->Release();
126                 stream->Release();
127                 return buffer;
128         }
129
130         hres = wicfactory->CreateFormatConverter(&converter);
131         if (hres != S_OK)
132         {
133
134                 Log::getInstance()->log("WICDecoder", Log::DEBUG, "Could not get source %d", hres);
135                 source->Release();
136                 decoder->Release();
137                 stream->Release();
138                 return buffer;
139         }
140
141         hres= converter->Initialize(source, GUID_WICPixelFormat32bppPBGRA,
142                 WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut);
143         if (hres != S_OK)
144         {
145
146                 Log::getInstance()->log("WICDecoder", Log::DEBUG, "Could not initialise converter %d", hres);
147                 converter->Release();
148                 source->Release();
149                 decoder->Release();
150                 stream->Release();
151                 return buffer;
152         }
153
154         ID2D1RenderTarget * rt=osd->LockOsdDrawing();
155
156
157         ID2D1Bitmap* bitmap;
158         hres = rt->CreateBitmapFromWicBitmap(converter, NULL, &bitmap);
159         if (hres == S_OK) {
160                 D2D1_SIZE_F size = bitmap->GetSize();
161                 pictInf.reference = (void*)bitmap;
162                 pictInf.width = size.width;
163                 pictInf.height = size.height;
164                 pictInf.image = bitmap;
165                 pictInf.decoder = this;
166                 pictInf.type = OsdVector::PictureInfo::D2DBitmap;
167                 pictInf.lindex = index;
168                 pictInfValid = true;
169                 if (freemem) {
170                         free(buffer);
171                 }
172         }
173
174         osd->UnlockOsdDrawing();
175
176         converter->Release();
177         source->Release();
178         decoder->Release();
179         stream->Release();
180
181         if (pictInfValid) return NULL;
182         else return buffer;
183 }
184
185 void WICPictDecoder::freeReference(void * ref)
186 {
187         ID2D1Bitmap* bitmap = (ID2D1Bitmap*)ref;
188         if (ref) bitmap->Release();
189 }
190
191 bool WICPictDecoder::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
192 {
193         if (!pictInfValid) return false;
194         pict_inf = pictInf;
195         pictInfValid = false;
196         return true;
197 }
198
199
200 //This is stuff for rendering the OSD
201
202 OsdWinVector::OsdWinVector()
203 {
204         d3ddevice10 = NULL;
205         d2dfactory = NULL;
206         currentosd_render.surf9 = NULL;
207         currentosd_render.surf10 = NULL;
208         currentosd_render.query9 = NULL;
209         currentosd_render.query10 = NULL;
210         currentosd_render.surfdxgi = NULL;
211         currentosd_render.sharedhandle = NULL;
212         currentosd_render.rendtarget2D = NULL;
213         currentosd_backbuffer = currentosd_backbuffer;
214         aspect_correction = 1.;
215         is_direct_write_initted = false;
216         dwritefac = NULL;
217         font = NULL;
218         fontface = NULL;
219         fontaspect_corr = 1.f;
220         dpix = dpiy = 72.f;
221         
222
223         ttchar_end.atlas = 0;
224         ttchar_end.position = 0;
225         ttbrush = NULL;
226
227         const wchar_t *fontname = L"Arial";
228         cur_fontname = (wchar_t*)malloc(2*wcslen(fontname) + 2);
229         wcscpy(cur_fontname, fontname);
230
231         WICPictDecoder * wicdecode = new WICPictDecoder(&reader, this);
232         reader.addDecoder(wicdecode);
233   
234 }
235
236 OsdWinVector::~OsdWinVector()
237 {
238         if (cur_fontname) free(cur_fontname);
239
240   if (initted) 
241   {
242                 shutdown();
243                 if (dwritefac) dwritefac->Release();
244                 if (!fontnames.size()) {
245                         std::vector<char*>::iterator itty = fontnames.begin();
246                         while (itty != fontnames.end()) {
247                                 free((void*)*itty);
248
249                                 itty++;
250                         }
251                 }
252                 /*if (!fontnames_keys.size()) {
253                         vector<char*>::iterator itty = fontnames_keys.begin();
254                         while (itty != fontnames_keys.end()) {
255                                 free((void*)*itty);
256
257                                 itty++;
258                         }
259                 }*/
260                 if (font) font->Release();
261                 if (fontface) fontface->Release();
262   }
263 }
264
265
266
267 int OsdWinVector::init()
268 {
269   if (initted) return 0;
270   reader.init();
271
272   if (!createDirect3D9Objects()) return 0;
273
274   // then create the Device
275
276   if (D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_9_1,
277           D3D10_1_SDK_VERSION, &d3ddevice10) != S_OK) {
278           Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D10 device!");
279           return 0;
280   }
281
282   if (d3ddevice10->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgidevice) != S_OK) {
283           Log::getInstance()->log("OSD", Log::WARN, "Could not query Dxgi device!");
284           return 0;
285   }
286
287   if (D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, __uuidof(ID2D1Factory),(void**) &d2dfactory) != S_OK) {
288           Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct2dfactory");
289           return 0;
290   }
291
292
293
294   queuemutex.lock();
295
296   HRESULT hres;
297   DXGI_SURFACE_DESC  surf_desc;
298   surf_desc.Width = OSD_BUFFER_WIDTH;
299   surf_desc.Height = OSD_BUFFER_HEIGHT;
300   surf_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
301   surf_desc.SampleDesc.Count = 1;
302   surf_desc.SampleDesc.Quality = 0;
303
304
305
306   D2D1_RENDER_TARGET_PROPERTIES rt_prop;
307   rt_prop.dpiX = rt_prop.dpiY = 0; 
308   rt_prop.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED);
309   rt_prop.minLevel = D2D1_FEATURE_LEVEL_9;
310   rt_prop.type = D2D1_RENDER_TARGET_TYPE_HARDWARE;
311   rt_prop.usage = D2D1_RENDER_TARGET_USAGE_NONE;
312
313   for (int i = 0; i < 3; i++) {
314           SurfaceInfo surfinfo;
315           surfinfo.surf9 = NULL;
316           surfinfo.surf10 = NULL;
317           surfinfo.query9 = NULL;
318           surfinfo.query10 = NULL;
319           surfinfo.surfdxgi = NULL;
320           surfinfo.sharedhandle = NULL;
321           surfinfo.rendtarget2D = NULL;
322
323           
324           hres = d3ddevice->CreateTexture(OSD_BUFFER_WIDTH, OSD_BUFFER_HEIGHT, 1, D3DUSAGE_RENDERTARGET, /*D3DFMT_A8R8G8B8*/D3DFMT_A8R8G8B8,
325                   D3DPOOL_DEFAULT, &surfinfo.surf9, &surfinfo.sharedhandle);
326           if (hres != S_OK) {
327                   Log::getInstance()->log("OSD", Log::WARN, "Could not create Texture for Direct3D9 !");
328                   queuemutex.unlock();
329                   return 0;
330           }
331
332           hres = d3ddevice->CreateQuery(D3DQUERYTYPE_EVENT, &surfinfo.query9);
333           if (hres != S_OK) {
334                   Log::getInstance()->log("OSD", Log::WARN, "Could not create Query for Direct3D9 !");
335                   queuemutex.unlock();
336                   return 0;
337           }
338
339           DXGI_SHARED_RESOURCE dxgi_res;
340           dxgi_res.Handle = surfinfo.sharedhandle;
341
342           ID3D10Resource * tempres = NULL;
343           hres = d3ddevice10->OpenSharedResource(surfinfo.sharedhandle, __uuidof(ID3D10Resource), (void**)&tempres);
344           if (hres != S_OK) {
345                   Log::getInstance()->log("OSD", Log::WARN, "Could not open resourcee for Direct3D10 !");
346                   queuemutex.unlock();
347                   return 0;
348           }
349
350           hres = tempres->QueryInterface(__uuidof(ID3D10Texture2D), (void**)&surfinfo.surf10);
351           if (hres != S_OK) {
352                   Log::getInstance()->log("OSD", Log::WARN, "Could not query surface for Direct3D10 !");
353                   queuemutex.unlock();
354                   return 0;
355           }
356           tempres->Release();
357
358
359           hres = surfinfo.surf10->QueryInterface(__uuidof(IDXGISurface), (void**)&surfinfo.surfdxgi);
360           if (hres != S_OK) {
361                   Log::getInstance()->log("OSD", Log::WARN, "Could not query surface for DXGI !");
362                   queuemutex.unlock();
363                   return 0;
364           }
365
366           hres = d2dfactory->CreateDxgiSurfaceRenderTarget(surfinfo.surfdxgi, &rt_prop, &surfinfo.rendtarget2D);
367           if (hres != S_OK) {
368                   Log::getInstance()->log("OSD", Log::WARN, "Could not create render target!");
369                   queuemutex.unlock();
370                   return 0;
371           }
372
373           surfinfo.rendtarget2D->GetDpi(&dpix, &dpiy);
374
375           if (i == 0) {
376                   surfinfo.rendtarget2D->CreateSolidColorBrush(D2D1::ColorF(0xFFFFFFFF, 1.f), &ttbrush);
377           }
378
379           D3D10_QUERY_DESC qdesc;
380           qdesc.Query = D3D10_QUERY_EVENT;
381           qdesc.MiscFlags = 0;
382
383           hres = d3ddevice10->CreateQuery(&qdesc, &surfinfo.query10);
384           if (hres != S_OK) {
385                   Log::getInstance()->log("OSD", Log::WARN, "Could not create Query for Direct2D Direct3D10 !");
386                   queuemutex.unlock();
387                   return 0;
388           }
389           allsurfs.push_back(surfinfo);
390           d3dtod2d.push(surfinfo);
391   }
392   aspect_correction = ((float)OSD_BUFFER_HEIGHT) / 576.f / (((float)OSD_BUFFER_WIDTH) / 720.f);
393
394   
395   queuemutex.unlock();
396
397   initPaths();
398
399   loadFont(false);
400
401   initted = true; // must set this here or create surface won't work
402
403   startRenderLoop();
404
405   return 1;
406 }
407
408
409 int OsdWinVector::shutdown()
410 {
411   if (!initted) return 0;
412   initted = 0;
413   stopRenderLoop();
414   reader.shutdown();
415   destroyPaths();
416
417
418   queuemutex.lock();
419   if (currentosd_render.surf9) {
420           currentosd_render.surf9 = NULL;
421   }
422
423   if (currentosd_backbuffer.surf9) {
424           currentosd_backbuffer.surf9 = NULL;
425   }
426
427
428
429   for (int i = 0; i < tt_atlas.size(); i++)
430   {
431           tt_atlas[i]->Release();
432   }
433   tt_atlas.clear();
434   tt_font_chars.clear();
435   ttbrush->Release();
436   ttbrush = NULL;
437
438   while (allsurfs.size()) {
439           SurfaceInfo surfinfo = allsurfs.front();
440           allsurfs.pop_front();
441           if (surfinfo.rendtarget2D) {
442                   ID2D1RenderTarget *temp = surfinfo.rendtarget2D;
443                   surfinfo.rendtarget2D = NULL;
444                   temp->Release();
445           }
446
447           if (surfinfo.surf9) {
448                   LPDIRECT3DTEXTURE9 temp = surfinfo.surf9;
449                   surfinfo.surf9 = NULL;
450                   temp->Release();
451           }
452
453           if (surfinfo.query9) {
454                   IDirect3DQuery9* temp = surfinfo.query9;
455                   surfinfo.query9 = NULL;
456                   temp->Release();
457           }
458
459           if (surfinfo.surf10) {
460                   ID3D10Texture2D * temp = surfinfo.surf10;
461                   surfinfo.surf10 = NULL;
462                   temp->Release();
463           }
464
465           if (surfinfo.surfdxgi) {
466                   IDXGISurface *temp = surfinfo.surfdxgi;
467                   surfinfo.surfdxgi = NULL;
468                   temp->Release();
469           }
470           if (surfinfo.query10) {
471                   ID3D10Query* temp = surfinfo.query10;
472                   surfinfo.query10 = NULL;
473                   temp->Release();
474           }
475   }
476
477   while (d3dtod2d.size()) d3dtod2d.pop();
478   while (d2dtod3d.size()) d2dtod3d.pop();
479
480   queuemutex.unlock();
481
482
483
484   if (d2dfactory) {
485           ID2D1Factory *temp = d2dfactory;
486           d2dfactory = NULL;
487           temp->Release();
488   }
489
490   if (d3ddevice10) {
491           ID3D10Device *temp = d3ddevice10;
492           d3ddevice10 = NULL;
493           temp->Release();
494   }
495
496   shutdownDirect3D9Objects();
497  
498
499   return 1;
500 }
501
502
503 void OsdWinVector::initPaths()
504 {
505         ID2D1PathGeometry *current = NULL;
506         ID2D1GeometrySink *currentsink = NULL;
507
508         d2dfactory->CreatePathGeometry(&current);
509         current->Open(&currentsink);
510         currentsink->BeginFigure(D2D1::Point2F(0, 0), D2D1_FIGURE_BEGIN_HOLLOW);
511
512         currentsink->AddLine(D2D1::Point2F(1.f, 0));
513
514         currentsink->EndFigure(D2D1_FIGURE_END_OPEN);
515         // HorzLine
516         std_paths[PIHorzLine] = current;
517
518         current = NULL;
519         currentsink->Close();
520         currentsink->Release();
521         currentsink=NULL;
522
523         d2dfactory->CreatePathGeometry(&current);
524         current->Open(&currentsink);
525         currentsink->BeginFigure(D2D1::Point2F(0, 0), D2D1_FIGURE_BEGIN_HOLLOW);
526
527         currentsink->AddLine(D2D1::Point2F(0, 1.f));
528         currentsink->EndFigure(D2D1_FIGURE_END_OPEN);
529
530         // VertLine
531         std_paths[PIVertLine] = current;
532
533         current = NULL;
534         currentsink->Close();
535         currentsink->Release();
536         currentsink = NULL;
537
538         d2dfactory->CreatePathGeometry(&current);
539         current->Open(&currentsink);
540         currentsink->BeginFigure(D2D1::Point2F(0, 0), D2D1_FIGURE_BEGIN_FILLED);
541
542         currentsink->AddLine(D2D1::Point2F(1, 0));
543         currentsink->AddLine(D2D1::Point2F(1, 1));
544         currentsink->AddLine(D2D1::Point2F(0, 1));
545         currentsink->EndFigure(D2D1_FIGURE_END_CLOSED);
546         // Rectabgle
547         std_paths[PIRectangle] = current;
548
549         current = NULL;
550         currentsink->Close();
551         currentsink->Release();
552         currentsink = NULL;
553
554         d2dfactory->CreatePathGeometry(&current);
555         current->Open(&currentsink);
556         currentsink->BeginFigure(D2D1::Point2F(0, 0.f), D2D1_FIGURE_BEGIN_FILLED);
557
558         currentsink->AddArc(D2D1::ArcSegment(
559                 D2D1::Point2F(0, 0.f),
560                 D2D1::SizeF(1.f, 1.f),
561                 0.0f,
562                 D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
563                 D2D1_ARC_SIZE_LARGE));
564
565         currentsink->EndFigure(D2D1_FIGURE_END_CLOSED);
566
567
568         // Point
569         std_paths[PIPoint] = current;
570
571         current = NULL;
572         currentsink->Close();
573         currentsink->Release();
574         currentsink = NULL;
575
576 }
577
578 void OsdWinVector::destroyPaths()
579 {
580         std_paths[PIHorzLine]->Release();
581         std_paths[PIVertLine]->Release();
582         std_paths[PIRectangle]->Release();
583         std_paths[PIPoint]->Release();
584
585 }
586
587
588
589 int  OsdWinVector::loadFont(bool newfont)
590 {
591         HRESULT hres;
592         if (!is_direct_write_initted)
593         {
594                 
595                 hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
596                         (IUnknown**)(&dwritefac));
597                 if (hres != S_OK)  {
598                         Log::getInstance()->log("OSD", Log::WARN, "Could not create DirectWrite Factory!");
599                         return 0;
600                 }
601
602                 is_direct_write_initted = true;
603         }
604
605         if (fontnames.size())
606         {
607                 fontnames.clear();
608         }
609
610         IDWriteFontCollection * fontcol = NULL;
611         if (dwritefac->GetSystemFontCollection(&fontcol) != S_OK) {
612                 Log::getInstance()->log("OSD", Log::WARN, "Could not get System Font Collection!");
613                 return 0;
614         }
615         UINT num_font = fontcol->GetFontFamilyCount();
616         for (UINT i = 0; i < num_font; i++) {
617                 IDWriteFontFamily * family=NULL;
618                 if (fontcol->GetFontFamily(i, &family)!=S_OK) continue;
619                 IDWriteLocalizedStrings* fam_name=NULL;
620                 if (family->GetFamilyNames(&fam_name) != S_OK) {
621                         family->Release();
622                         continue;
623                 }
624                 UINT32 id = 0;
625                 BOOL exist = false;
626                 if (fam_name->FindLocaleName(L"en-us", &id, &exist) == S_OK) {
627                         if (!exist) id = 0;
628                         UINT32  strlen=0;
629                         fam_name->GetStringLength(id, &strlen);
630                         wchar_t * stringbuf = new wchar_t[strlen + 1];
631                         
632                         fam_name->GetString(id, stringbuf, strlen+1);
633
634                         int strlenutf8 = WideCharToMultiByte(CP_UTF8, 0, stringbuf, -1,
635                                 NULL, 0, 0, NULL);
636                         char *stringbufutf8 = new char[strlenutf8 + 1];
637                         WideCharToMultiByte(CP_UTF8, 0, stringbuf, -1,
638                                 stringbufutf8, strlenutf8+1, 0, NULL);
639                 
640
641                         if (wcscmp(cur_fontname, stringbuf) == 0) {
642                                 IDWriteFont* new_font;
643                                 if (family->GetFirstMatchingFont(DWRITE_FONT_WEIGHT_NORMAL,
644                                         DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &new_font) == S_OK) {
645                                         IDWriteFontFace *newfontface = NULL;
646                                         new_font->CreateFontFace(&newfontface);
647
648                                         IDWriteFont* temp_font = font;
649                                         IDWriteFontFace* temp_fontface = fontface;
650                                         font = new_font;
651                                         fontface = newfontface;
652
653                                         if (temp_font) temp_font->Release();    
654                                         if (temp_fontface) temp_fontface->Release();
655                                 }
656                         }
657
658                         delete[] stringbuf;
659                         fontnames.push_back(stringbufutf8);
660                 }
661                 fam_name->Release();
662                 family->Release();
663         }
664         fontcol->Release();
665         
666         if (font) {
667                 DWRITE_FONT_METRICS metrics;
668                 font->GetMetrics(&metrics);
669                 fontheight = ((float)( metrics.ascent + metrics.descent + metrics.lineGap))*13.f 
670                         / ((float)metrics.designUnitsPerEm) / 576.f * ((float)OSD_BUFFER_HEIGHT)/72.f*dpiy;
671                 fontzero = ((float)(metrics.ascent))*13.f
672                         / ((float)metrics.designUnitsPerEm) / 576.f * ((float)OSD_BUFFER_HEIGHT) / 72.f*dpiy;
673
674                 fontaspect_corr = ((float)OSD_BUFFER_HEIGHT) / ((float)OSD_BUFFER_WIDTH) * 720.f / 576.f;
675                 
676
677                 for (UINT32 i = 0; i<256; i++) {
678                         DWRITE_GLYPH_METRICS glyph_metrics;
679                         UINT16 glyph_index;
680                         fontface->GetGlyphIndices(&i, 1, &glyph_index);
681                         HRESULT hres=fontface->GetDesignGlyphMetrics(&glyph_index, 1, &glyph_metrics, FALSE);
682                 
683                         if (hres == S_OK) {
684                                 byte_char_width[i] = ((float)glyph_metrics.advanceWidth)*13.f
685                                         / ((float)metrics.designUnitsPerEm)  *fontaspect_corr / 72.f*dpix;
686                         }
687                         else {
688                                 byte_char_width[i] = 0.f;
689                         }
690                 }
691
692                 
693
694
695         }
696
697
698         return 1;
699 }
700
701
702 OsdWinVector::TTIndex OsdWinVector::loadTTchar(cTeletextChar c)
703 {
704         /*      map<unsigned int, TTIndex> tt_font_chars;
705         vector<ID2D1Bitmap *> tt_atlas;
706         TTIndex ttchar_end;*/
707
708
709         unsigned int glyph_index = c.getGlyphIndex();
710         std::map<unsigned int, TTIndex>::iterator glypos = tt_font_chars.find(glyph_index);
711         if (glypos != tt_font_chars.end())
712         {
713                 return (*glypos).second;
714         }
715         TTIndex our_index = ttchar_end;
716
717         unsigned int buffer[10];
718         unsigned int * charmap = GetFontChar(c, buffer);
719         if (!charmap) { //invalid char
720                 our_index.atlas = our_index.position = 0;
721                 return our_index;
722         }
723
724
725
726         // Now we have to determine, if the atlas is already created
727         if (our_index.atlas == tt_atlas.size()) {
728                 //Now we have to create the atlas
729                 ID2D1Bitmap * atlas = NULL;
730                 D2D1_SIZE_U size;
731                 size.height = 120;
732                 size.width = 120;
733                 D2D1_BITMAP_PROPERTIES bitmap_prop;
734                 bitmap_prop.dpiX = dpix;
735                 bitmap_prop.dpiY = dpiy;
736                 bitmap_prop.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
737                 bitmap_prop.pixelFormat.alphaMode = D2D1_ALPHA_MODE_STRAIGHT;
738
739                 HRESULT hres = currentosd_backbuffer.rendtarget2D->CreateBitmap(size, bitmap_prop, &atlas);
740
741                 if (hres != S_OK) {
742                         Log::getInstance()->log("OsdWinVector", Log::DEBUG, "CreateBitmap for atlas failed %d", hres);
743                         atlas = NULL;
744                         our_index.atlas = our_index.position = 0;
745                         return our_index;
746                 }
747                 tt_atlas.push_back(atlas);
748
749         }
750
751         unsigned char buffer_final[120];
752         for (int i = 0; i<10; i++) {
753                 for (int j = 0; j < 12; j++) {
754                         buffer_final[i*12+j] = ((charmap[i] >> (16-j)) & 1)? 0xFF: 0x00;
755                 }
756         }
757
758         D2D1_RECT_U dst_rect = { (our_index.position % 10)*12,
759                 (our_index.position /10) *10,
760                 (our_index.position % 10+1)*12,
761                 (our_index.position / 10+1)*10,
762         };
763
764         HRESULT hres=tt_atlas[our_index.atlas]->CopyFromMemory(&dst_rect, buffer_final, 12);
765
766         if (hres != S_OK) {
767                 Log::getInstance()->log("OsdWinVector", Log::DEBUG, "CopyFromMemory for atlas failed %d", hres);
768                 our_index.atlas = our_index.position = 0;
769                 return our_index;
770         }
771
772         tt_font_chars[glyph_index] = our_index;
773         ttchar_end.position++;
774         if (ttchar_end.position == 120) {
775                 ttchar_end.position = 0;
776                 ttchar_end.atlas++;
777         }
778         return our_index;
779
780 }
781
782 int OsdWinVector::getFontNames(const char *** names, const char *** names_keys)
783 {
784         *names = (const char**)&(fontnames[0]);
785         *names_keys = (const char**)&(fontnames/*_keys*/[0]);
786         return fontnames.size();
787 }
788
789 void OsdWinVector::setFont(const char * fontname) {
790
791         wchar_t * wfontname= new wchar_t[strlen(fontname)+1];
792
793         MultiByteToWideChar(CP_UTF8, 0, fontname, -1,
794                 wfontname, strlen(fontname) + 1);
795
796         if (wcscmp(wfontname, cur_fontname)) {
797                 // new font!
798                 if (cur_fontname) free(cur_fontname);
799                 cur_fontname = (wchar_t*)malloc(2*wcslen(wfontname) + 2);
800                 wcscpy(cur_fontname, wfontname);
801                 loadFont(true);
802
803         }
804
805
806         delete[] wfontname;
807
808 }
809
810
811
812 void OsdWinVector::drawSetTrans(SurfaceCommands & sc)
813 {
814         D2D1::Matrix3x2F trans = D2D1::Matrix3x2F::Identity();
815
816         trans = trans*D2D1::Matrix3x2F::Scale(((float)OSD_BUFFER_WIDTH) / 720.f, ((float)OSD_BUFFER_HEIGHT) / 576.f);
817         trans=D2D1::Matrix3x2F::Translation(0.f + sc.x,  sc.y)*trans;
818
819         currentosd_backbuffer.rendtarget2D->SetTransform(trans);
820
821         clip_shift_x = sc.x;
822         clip_shift_y = sc.y;
823 }
824
825 void OsdWinVector::executeDrawCommand(SVGCommand & command)
826 {
827         D2D1::Matrix3x2F save_matrix;
828         D2D1::Matrix3x2F save_matrix2;
829
830
831         switch (command.instr) {
832         case DrawPath: {
833                 currentosd_backbuffer.rendtarget2D->GetTransform(&save_matrix);
834                 
835                 D2D1::Matrix3x2F matrix;
836                 matrix =  
837                         D2D1::Matrix3x2F::Scale(command.w, command.h)*D2D1::Matrix3x2F::Translation(command.x, command.y)*save_matrix;
838                 currentosd_backbuffer.rendtarget2D->SetTransform(matrix);
839                 currentosd_backbuffer.rendtarget2D->FillGeometry(std_paths[command.target.path_index], 
840                         (ID2D1Brush*)command.reference);
841
842                 currentosd_backbuffer.rendtarget2D->SetTransform(save_matrix);
843
844         } break;
845         case DrawImage: {
846                                                 currentosd_backbuffer.rendtarget2D->GetTransform(&save_matrix);
847                                                 ID2D1Bitmap * bitmap = (ID2D1Bitmap*)command.target.image;
848                                                 if (!bitmap) return;
849                                                 D2D1_SIZE_F  size=bitmap->GetSize(); 
850                                                 
851                                                 D2D1::Matrix3x2F matrix;
852                                                 
853
854                                                 if (command.reference) { //special behaviour for bw images they act as a mask on the current paint
855                                                         matrix =
856                                                                 D2D1::Matrix3x2F::Scale(1.f*aspect_correction, 1.f)
857                                                                 *D2D1::Matrix3x2F::Translation(command.x, command.y)*save_matrix;
858                                                 }
859                                                 else {
860
861                                                         float scalex = command.w / size.width;
862                                                         float scaley = command.h / size.height;
863                                                         float tx = command.x;
864                                                         float ty = command.y;
865                                                         if (command.corner == TopLeftLimited) {
866                                                                 if (scalex != 0.f && scaley != 0.f) {
867                                                                         float imageaspect = size.width / size.height;
868                                                                         float boxaspect = command.w / command.h / aspect_correction;
869                                                                         if (imageaspect > boxaspect) {
870                                                                                 scaley = 0.f;
871                                                                                 ty += (command.h - size.height * scalex / aspect_correction)*0.5f;
872                                                                         }
873                                                                         else {
874                                                                                 scalex = 0.f;
875                                                                                 tx += (command.w - size.width * scaley*aspect_correction)*0.5f;
876                                                                         }
877
878                                                                 }
879
880                                                         }
881                                                         if (scalex == 0.f && scaley == 0.f) {
882                                                                 scalex = aspect_correction;
883                                                                 scaley = 1.f;
884                                                         }
885                                                         else if (scalex == 0.f) {
886                                                                 scalex = scaley*aspect_correction;
887                                                         }
888                                                         else if (scaley == 0.f) {
889                                                                 scaley = scalex / aspect_correction;
890                                                         }
891
892
893                                                         if (command.corner == BottomRight || command.corner == BottomLeft || command.corner == BottomMiddle)
894                                                         {
895                                                                 ty -= size.height * scaley;
896                                                         }
897
898                                                         if (command.corner == BottomRight || command.corner == TopRight)
899                                                         {
900                                                                 tx -= size.width * scalex;
901                                                         }
902
903                                                         if (command.corner == BottomMiddle || command.corner == TopMiddle)
904                                                         {
905                                                                 tx -= size.width * scalex *0.5f;
906                                                         }
907
908                                                         matrix =
909                                                                 D2D1::Matrix3x2F::Scale(scalex, scaley)*D2D1::Matrix3x2F::Translation(tx, ty)*save_matrix;
910
911                                         
912                                                 }
913
914                                                 currentosd_backbuffer.rendtarget2D->SetTransform(matrix);
915
916                                                 if (command.reference) {
917                                                         currentosd_backbuffer.rendtarget2D->FillOpacityMask(bitmap, (ID2D1Brush*)command.reference, D2D1_OPACITY_MASK_CONTENT_GRAPHICS);
918                                                         
919                                                 }
920                                                 else 
921                                                 {
922                                                         currentosd_backbuffer.rendtarget2D->DrawBitmap(bitmap);
923                                                 }
924                         
925                                         
926
927                                                 
928                                                 currentosd_backbuffer.rendtarget2D->SetTransform(save_matrix);
929
930
931         } break;
932         case DrawGlyph: {
933                                                 currentosd_backbuffer.rendtarget2D->GetTransform(&save_matrix);
934
935                                                 D2D1::Matrix3x2F matrix;
936                                                 matrix = D2D1::Matrix3x2F::Scale(fontaspect_corr, 1.f)*
937                                                         D2D1::Matrix3x2F::Translation(command.x, command.y + fontzero)*save_matrix;
938                                                 currentosd_backbuffer.rendtarget2D->SetTransform(matrix);
939                                                 UINT32 tchar = command.target.textchar;
940                                                 UINT16 glyphindex;
941                                                 DWRITE_GLYPH_RUN glyph_run;
942                                                 glyph_run.fontEmSize = 13.f / (74.f / 96.f);
943                                                 glyph_run.fontFace=fontface;
944                                                 glyph_run.glyphCount=1;
945                                                 glyph_run.glyphIndices = &glyphindex;
946
947                                                 fontface->GetGlyphIndices(&tchar, 1, &glyphindex);
948                                         
949                                                 FLOAT zero = 0.f;
950                                                 DWRITE_GLYPH_OFFSET zero2 = { 0.f, 0.f };
951                                                 glyph_run.glyphAdvances=&zero;
952                                                 glyph_run.glyphOffsets=&zero2;
953                                                 glyph_run.isSideways=false;
954                                                 glyph_run.bidiLevel=0;
955                                                 D2D1_POINT_2F pos = { 0.f, 0.f };
956
957                                                 currentosd_backbuffer.rendtarget2D->DrawGlyphRun(pos, &glyph_run,
958                                                         (ID2D1Brush*)command.reference);                
959                                                 currentosd_backbuffer.rendtarget2D->SetTransform(save_matrix);
960
961         } break;
962         case DrawTTchar:{
963                                                 cTeletextChar tchar;
964                                                 tchar.setInternal(command.target.ttchar);
965                                                 currentosd_backbuffer.rendtarget2D->GetTransform(&save_matrix);
966
967                                                 enumTeletextColor ttforegcolour = tchar.GetFGColor();
968                                                 enumTeletextColor ttbackgcolour = tchar.GetBGColor();
969                                                 if (tchar.GetBoxedOut()) {
970                                                         ttforegcolour = ttcTransparent;
971                                                         ttbackgcolour = ttcTransparent;
972                                                 }
973                                                 D2D1::Matrix3x2F matrix;
974                                                 matrix = D2D1::Matrix3x2F::Scale(1.5f+0.05f, 2.f)
975                                                         *D2D1::Matrix3x2F::Translation(command.x + command.w*11.85f*1.4f, command.y + command.h*19.75f)
976                                                         *save_matrix;
977
978                                                 currentosd_backbuffer.rendtarget2D->SetTransform(matrix);
979
980
981                                                 Colour color = Surface::enumTeletextColorToCoulour(ttbackgcolour);
982
983                                                 ttbrush->SetColor(D2D1::ColorF(color.rgba(), ((float)color.alpha) / 255.f));
984                                                 
985                                                 cTeletextChar filled;
986                                                 filled.setInternal(0x187f);
987                                                 TTIndex glyph_index = loadTTchar(filled);
988
989                                                 {
990                                                         D2D1_RECT_F src_rect = { (glyph_index.position % 10)*12.f,
991                                                                 (glyph_index.position / 10) *10.f,
992                                                                 (glyph_index.position % 10 + 1)*12.f,
993                                                                 (glyph_index.position / 10 + 1)*10.f,
994                                                         };
995
996
997                                                         currentosd_backbuffer.rendtarget2D->FillOpacityMask(tt_atlas[glyph_index.atlas], ttbrush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS,
998                                                                 NULL, &src_rect);
999                                                 }
1000
1001                                                 color = Surface::enumTeletextColorToCoulour(ttforegcolour);
1002                                                 ttbrush->SetColor(D2D1::ColorF(color.rgba(), ((float)color.alpha) / 255.f));
1003
1004                                         
1005                                                 glyph_index = loadTTchar(tchar);
1006
1007                                                 {
1008                                                         D2D1_RECT_F src_rect = { (glyph_index.position % 10)*12.f,
1009                                                                 (glyph_index.position / 10) *10.f,
1010                                                                 (glyph_index.position % 10 + 1)*12.f,
1011                                                                 (glyph_index.position / 10 + 1)*10.f,
1012                                                         };
1013
1014
1015                                                         currentosd_backbuffer.rendtarget2D->FillOpacityMask(tt_atlas[glyph_index.atlas], ttbrush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS,
1016                                                                 NULL, &src_rect);
1017                                                 }
1018
1019
1020                                                 currentosd_backbuffer.rendtarget2D->SetTransform(save_matrix);
1021                                         
1022
1023         }break;
1024         case DrawClipping: {
1025                                                    currentosd_backbuffer.rendtarget2D->GetTransform(&save_matrix);
1026                                                    currentosd_backbuffer.rendtarget2D->SetTransform(D2D1::IdentityMatrix());
1027
1028                                                    D2D1_RECT_F coords = { ((command.x + clip_shift_x)*((float)OSD_BUFFER_WIDTH) / 720.f),
1029                                                            (( command.y + clip_shift_y )*((float)OSD_BUFFER_HEIGHT) / 576.f),
1030                                                            ((command.x + clip_shift_x+command.w - 1.f)*((float)OSD_BUFFER_WIDTH) / 720.f),
1031                                                            (command.y + clip_shift_y+(command.h - 1.f)*((float)OSD_BUFFER_HEIGHT) / 576.f) };
1032                                                    if (command.w == 0.f && command.h == 0.f) {
1033                                                            while (num_clips > 0) {
1034                                                                    num_clips--;
1035                                                                    currentosd_backbuffer.rendtarget2D->PopAxisAlignedClip();
1036                                                            }
1037                                                    } else {
1038                                                            num_clips++;
1039                                                            currentosd_backbuffer.rendtarget2D->PushAxisAlignedClip(coords, D2D1_ANTIALIAS_MODE_ALIASED);
1040                                                         
1041                                                    }
1042                                                    currentosd_backbuffer.rendtarget2D->SetTransform(save_matrix);
1043         } break;
1044         }
1045 }
1046
1047 float OsdWinVector::getFontHeight()
1048 {
1049         return fontheight; 
1050 }
1051 float OsdWinVector::getCharWidth(wchar_t c)
1052 {
1053         if (c<256) return byte_char_width[c];
1054         if (!font) return 13.f;
1055         DWRITE_FONT_METRICS metrics;
1056         font->GetMetrics(&metrics);
1057
1058         
1059         DWRITE_GLYPH_METRICS glyph_metrics;
1060         UINT16 glyph_index;
1061         UINT32 tchar = c;
1062         fontface->GetGlyphIndices(&tchar, 1, &glyph_index);
1063         fontface->GetDesignGlyphMetrics(&glyph_index, 1, &glyph_metrics, FALSE);
1064
1065         return ((float)glyph_metrics.advanceWidth)*13.f
1066                 / ((float)metrics.designUnitsPerEm) *fontaspect_corr / 72.f*dpiy;
1067         
1068
1069 }
1070
1071 void OsdWinVector::getScreenSize(int &width, int &height)
1072 {
1073         width = OSD_BUFFER_WIDTH;
1074         height = OSD_BUFFER_HEIGHT;
1075 }
1076
1077 void OsdWinVector::getRealScreenSize(int &width, int &height)
1078 {
1079         width = BACKBUFFER_WIDTH;
1080         height = BACKBUFFER_HEIGHT;
1081 }
1082
1083 bool OsdWinVector::screenShot(void *buffer, int width, int height, bool osd /*include osd*/) 
1084 {
1085   //screen->screenShot(fileName);
1086         return false;
1087 }
1088
1089 LPDIRECT3DTEXTURE9 OsdWinVector::getNextOsdTexture()
1090 {
1091         queuemutex.lock();
1092         if (d2dtod3d.size())
1093         {
1094                 SurfaceInfo surfinfo = d2dtod3d.front();
1095                 //Now we have to check, if the resource is ready, or busy somewhere else
1096            // if (surfinfo.query10->GetData(NULL, 0, D3D10_ASYNC_GETDATA_DONOTFLUSH) == S_OK) {
1097                         //the surface is ready
1098                         if (currentosd_render.surf9) {
1099                                 currentosd_render.query9->Issue(D3DISSUE_END); //mark the end of the 9 api access
1100                                 d3dtod2d.push(currentosd_render);
1101                         }
1102                         currentosd_render = surfinfo;
1103                         d2dtod3d.pop();
1104                 //}
1105         }
1106         queuemutex.unlock();
1107         
1108         return currentosd_render.surf9;
1109 }
1110
1111 void  OsdWinVector::updateOsd()
1112 {
1113
1114         queuemutex.lock();
1115         if (d3dtod2d.size())
1116         {
1117                 currentosd_backbuffer = d3dtod2d.front();
1118                 //Now we have to check, if the resource is ready, or busy somewhere else
1119                 if (currentosd_backbuffer.query9->GetData(NULL, 0, 0) == S_OK) {
1120                         
1121
1122                         //queuemutex.unlock();
1123                         currentosd_backbuffer.query10->Begin();
1124                 
1125                         currentosd_backbuffer.rendtarget2D->BeginDraw();
1126                         currentosd_backbuffer.rendtarget2D->Clear(D2D1::ColorF(0.f, 0.f, 0.f, 0.0f));
1127                         currentosd_backbuffer.rendtarget2D->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
1128                 
1129                         num_clips = 0;
1130                         // We can draw here
1131                         drawSurfaces();
1132                         while (num_clips>0) {
1133                                 currentosd_backbuffer.rendtarget2D->PopAxisAlignedClip();
1134                                 num_clips--;
1135                         }
1136
1137                         currentosd_backbuffer.rendtarget2D->EndDraw();
1138                         currentosd_backbuffer.rendtarget2D->Flush();
1139                         d3ddevice10->Flush();
1140                         currentosd_backbuffer.query10->End();
1141
1142                         //queuemutex.lock();
1143                         d3dtod2d.pop();
1144                         d2dtod3d.push(currentosd_backbuffer);
1145                                 
1146                 }
1147
1148         }
1149         
1150         queuemutex.unlock();
1151
1152 }
1153
1154 ID2D1RenderTarget * OsdWinVector::LockOsdDrawing()
1155 {
1156         queuemutex.lock();
1157         if (d3dtod2d.size())
1158         {
1159                 currentosd_backbuffer=d3dtod2d.front();
1160                 return currentosd_backbuffer.rendtarget2D;
1161         }
1162         queuemutex.unlock();
1163
1164         int loop = 0;
1165         while (loop < 100) {
1166                 queuemutex.lock();
1167                 if (d3dtod2d.size())
1168                 {
1169                         currentosd_backbuffer = d3dtod2d.front();
1170                         return currentosd_backbuffer.rendtarget2D;
1171                 }
1172                 queuemutex.unlock();
1173
1174                 MILLISLEEP(100);
1175                 loop++;
1176         }
1177
1178         currentosd_backbuffer.surf10 = NULL;
1179         currentosd_backbuffer.surf9 = NULL;
1180         return NULL;
1181
1182 }
1183 void OsdWinVector::UnlockOsdDrawing()
1184 {
1185         queuemutex.unlock();
1186 }
1187
1188 void OsdWinVector::lostDestroyObjects()
1189 {
1190
1191 }
1192
1193 void OsdWinVector::lostRecreateObjects()
1194 {
1195
1196 }
1197
1198
1199 void OsdWinVector::getTextureCoordinates(FLOAT* x, FLOAT* y)
1200 {
1201         *x = 1.f;
1202         *y = 1.f;
1203 }
1204
1205
1206
1207
1208 void OsdWinVector::destroyImageRef(ImageIndex index)
1209 {
1210         ID2D1Bitmap* bitmap = (ID2D1Bitmap*)index;
1211         if (bitmap) bitmap->Release();
1212 }
1213
1214
1215 bool OsdWinVector::getStaticImageData(unsigned int static_id, UCHAR **userdata, ULONG *length)
1216 {
1217         if (sa_MAX>static_id) {
1218                 HRSRC hrc = FindResource(GetModuleHandle(NULL), ext_pict_name[static_id], RT_RCDATA);
1219                 *length = SizeofResource(GetModuleHandle(NULL), hrc);
1220                 *userdata = (UCHAR*) LockResource(LoadResource(GetModuleHandle(NULL), hrc));
1221
1222                 return true;
1223         }
1224
1225         *userdata = NULL;
1226         *length = 0;
1227         return false;
1228
1229 }
1230
1231 void  OsdWinVector::createPicture(struct PictureInfo& pict_inf)
1232 {
1233         
1234         Log::getInstance()->log("OsdWinVector", Log::DEBUG, "TVMedia Create Picture %d", pict_inf.type);
1235         if (pict_inf.type == PictureInfo::D2DBitmap) {
1236                 bool static_image = true;
1237                 if (pict_inf.lindex & 0xffffffff) static_image = false;
1238
1239                 Message* m = new  Message();
1240                 // We have a pictures! send a message to ourself, to switch to gui thread
1241                 m->from = this;
1242                 m->to = Command::getInstance();
1243                 m->data = pict_inf.reference;
1244                 if (!static_image) {
1245                         m->message = Message::NEW_PICTURE;
1246                         m->tag = pict_inf.lindex;
1247                 }
1248                 else {
1249                         m->message = Message::NEW_PICTURE_STATIC;
1250                         m->tag = pict_inf.lindex >> 32LL;
1251                 }
1252                 MessageQueue::getInstance()->postMessage(m); // inform command about new picture
1253
1254         } else {
1255                 pict_inf.decoder->freeReference(pict_inf.reference);
1256         }
1257         
1258 }
1259
1260
1261 ImageIndex OsdWinVector::createMonoBitmap(void *base, int width, int height)
1262 {
1263         // First we have  to convert it to 8 bit alpha, we could use WIC but actually writing this code is not hard to port from base class
1264
1265         LockOsdDrawing();
1266
1267         int x, y;
1268         unsigned char *basechar = (unsigned char*) base;
1269         unsigned int bytesIn, bitsIn;
1270         int widthBytes = width / 8;
1271
1272         unsigned char *alphamem = (unsigned char*)malloc(width*height);
1273         unsigned char *alphamemrun = alphamem;
1274
1275         for (y = 0; y < height; y++) {
1276                 for (x = 0; x < width; x++) {
1277                         bytesIn = (y * widthBytes) + (int)(x / 8);
1278                         bitsIn = x % 8;
1279                         (*alphamemrun) = ((basechar[bytesIn] >> (7 - bitsIn)) & 0x01) ? 0xFF : 0x00; 
1280                         alphamemrun++;
1281                 }
1282         }
1283         D2D1_SIZE_U size;
1284         size.height = height;
1285         size.width = width;
1286         D2D1_BITMAP_PROPERTIES bitmap_prop;
1287         bitmap_prop.dpiX = dpix;
1288         bitmap_prop.dpiY = dpiy;
1289         bitmap_prop.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1290         bitmap_prop.pixelFormat.alphaMode = D2D1_ALPHA_MODE_STRAIGHT;
1291
1292         ID2D1Bitmap *bitmap = NULL;
1293
1294         HRESULT hres = currentosd_backbuffer.rendtarget2D->CreateBitmap(size, alphamem, width, bitmap_prop, &bitmap);
1295
1296         if (hres != S_OK) {
1297                 Log::getInstance()->log("OsdWinVector", Log::DEBUG, "CreateBitmap failed %d", hres);
1298                 bitmap = NULL;
1299         }
1300
1301         free(alphamem);
1302
1303         UnlockOsdDrawing();
1304
1305         return (void*)bitmap;
1306
1307 }
1308
1309 ImageIndex OsdWinVector::createImagePalette(int width, int height, const unsigned char *image_data, const unsigned int*palette_data)
1310 {
1311         // First we have  to convert it to 32 bit RGBA, we could use WIC but actually writing this code is not hard to port from base class
1312
1313         LockOsdDrawing();
1314
1315         int x, y;
1316         UINT32 *mem = (UINT32*)malloc(width*height*sizeof(UINT32));
1317         UINT32 *memrun = mem;
1318         const unsigned char* image_run = image_data;
1319
1320         for (y = 0; y < height; y++) {
1321                 for (x = 0; x < width; x++) {
1322
1323                         (*memrun) = palette_data[(*image_run)];
1324                         memrun++;
1325                         image_run++;
1326                 }
1327         }
1328         D2D1_SIZE_U size;
1329         size.height = height;
1330         size.width = width;
1331         D2D1_BITMAP_PROPERTIES bitmap_prop;
1332         bitmap_prop.dpiX = dpix;
1333         bitmap_prop.dpiY = dpiy;
1334         bitmap_prop.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
1335         bitmap_prop.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1336
1337         ID2D1Bitmap *bitmap = NULL;
1338
1339         HRESULT hres = currentosd_backbuffer.rendtarget2D->CreateBitmap(size, mem, width*sizeof(UINT32), bitmap_prop, &bitmap);
1340
1341         if (hres != S_OK) {
1342                 Log::getInstance()->log("OsdWinVector", Log::DEBUG, "CreateBitmap failed %d", hres);
1343                 bitmap = NULL;
1344         }
1345
1346         free(mem);
1347
1348         UnlockOsdDrawing();
1349
1350         return (void*)bitmap;
1351
1352 }
1353
1354 void OsdWinVector::destroyStyleRef(VectorHandle index)
1355 {
1356         if (!initted) return;
1357         ID2D1Brush *brush = (ID2D1Brush*)(index);
1358         brush->Release();
1359         
1360 }
1361
1362 VectorHandle OsdWinVector::createStyleRef(const DrawStyle &c)
1363 {
1364         LockOsdDrawing();
1365
1366         switch (c.ft) {
1367         case DrawStyle::Color: {
1368                 ID2D1SolidColorBrush * newbrush=NULL;
1369                 currentosd_backbuffer.rendtarget2D->CreateSolidColorBrush(
1370                                 D2D1::ColorF(c.rgba(),((float)c.alpha)/255.f),
1371                                 &newbrush);
1372                 UnlockOsdDrawing();
1373                 return newbrush;
1374         } break;
1375         case DrawStyle::GradientLinear: 
1376         case DrawStyle::GradientRadial: {
1377                 D2D1_GRADIENT_STOP grad_stop[5];
1378                 grad_stop[0].color = D2D1::ColorF(c.rgba());
1379                 grad_stop[0].position = 0.0f;
1380
1381                 for (int i = 0; i < (c.num_colors - 1); i++) {
1382                         grad_stop[i + 1].color = D2D1::ColorF(c.grad_col[i].rgba(), ((float)c.grad_col[i].alpha) / 255.f);
1383                         grad_stop[i + 1].position = c.grad_pos[i];
1384                 }
1385                 grad_stop[c.num_colors].color = D2D1::ColorF(c.grad_col[c.num_colors - 1].rgba(), ((float)c.grad_col[c.num_colors - 1].alpha) / 255.f);
1386                 grad_stop[c.num_colors].position = 1.f;
1387
1388                 ID2D1GradientStopCollection *gradstopobj;
1389
1390                 currentosd_backbuffer.rendtarget2D->CreateGradientStopCollection(
1391                         grad_stop,
1392                         c.num_colors+1,
1393                         D2D1_GAMMA_2_2,
1394                         D2D1_EXTEND_MODE_CLAMP,
1395                         &gradstopobj
1396                         );
1397
1398                 if (c.ft == DrawStyle::GradientLinear) {
1399                         ID2D1LinearGradientBrush * newbrush=NULL;
1400                         currentosd_backbuffer.rendtarget2D->CreateLinearGradientBrush(
1401                                 D2D1::LinearGradientBrushProperties(
1402                                 D2D1::Point2F(c.x1, c.y1),
1403                                 D2D1::Point2F(c.x2, c.y2)),
1404                                 gradstopobj,
1405                                 &newbrush
1406                                 );
1407                         gradstopobj->Release();
1408                         UnlockOsdDrawing();
1409                         return newbrush;
1410                 }
1411                 if (c.ft == DrawStyle::GradientRadial) {
1412                         ID2D1RadialGradientBrush * newbrush = NULL;
1413                         currentosd_backbuffer.rendtarget2D->CreateRadialGradientBrush(
1414                                 D2D1::RadialGradientBrushProperties(
1415                                 D2D1::Point2F(c.x1, c.y1),
1416                                 D2D1::Point2F(c.x2, c.y2),c.r,c.r),
1417                                 gradstopobj,
1418                                 &newbrush
1419                                 );
1420                         gradstopobj->Release();
1421                         UnlockOsdDrawing();
1422                         return newbrush;
1423                 }                               
1424
1425         } break;
1426         };
1427
1428         UnlockOsdDrawing();
1429         return NULL;
1430
1431 }
1432
1433