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