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