ecere/gfx: Font outline support
[sdk] / ecere / src / gfx / drivers / DirectDrawDisplayDriver.ec
1 namespace gfx::drivers;
2
3 import "instance"
4
5 #if defined(__WIN32__)
6
7 #define Method _Method
8 #define uint _uint
9 #define byte _byte
10 #define int64 _int64
11 #define String _String
12 #define Mutex _Mutex
13 #define Size _Size
14 #define Platform _Platform
15
16 #if defined(__MINGW32__) && !defined(_W64)
17 #undef DECLARE_INTERFACE
18 #define DECLARE_INTERFACE(i) \
19    interface i { CONST_VTABLE struct i##Vtbl *lpVtbl; }; \
20    typedef CONST_VTABLE struct i##Vtbl i##Vtbl; \
21    CONST_VTABLE struct i##Vtbl
22 #endif
23
24 #define UNICODE
25
26 #include <ddraw.h>
27
28 #undef Method
29 #undef uint
30 #undef byte
31 #undef int64
32 #undef String
33 #undef Mutex
34 #undef Size
35 #undef Platform
36
37 import "Display"
38
39 class DDrawDisplay : LFBDisplay
40 {
41    IDirectDrawSurface * front;
42    IDirectDrawSurface * back;
43    IDirectDrawPalette * palette;
44    DDSURFACEDESC frontDesc, backDesc;
45    IDirectDraw * directDraw;
46    HDC hdc;
47
48    void Unlock()
49    {
50       if(backDesc.lpSurface && bitmap.picture)
51       {
52          IDirectDrawSurface_Unlock(back, backDesc.lpSurface);
53          bitmap.picture = null;
54       }
55    }
56
57    bool Lock()
58    {
59       bool result = false;
60       if(!back || bitmap.picture)
61          result = true;
62       else
63       {
64          uint ddrawResult = IDirectDrawSurface_Lock(back, null, &backDesc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, null);
65          if(ddrawResult == DDERR_SURFACELOST) // !display.full_screen
66          {
67
68             IDirectDrawSurface_Restore(back);
69             ddrawResult = IDirectDrawSurface_Lock(back, null, &backDesc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, null);
70          }
71          if(!ddrawResult)
72          {
73             bool validFormat = true;
74             switch(backDesc.ddpfPixelFormat.dwRGBBitCount)
75             {
76                case 8: bitmap.pixelFormat = pixelFormat8; break;
77                case 15: bitmap.pixelFormat = pixelFormat555; break;
78                case 16:
79                   if(backDesc.ddpfPixelFormat.dwGBitMask == 0x3E0)
80                      bitmap.pixelFormat = pixelFormat555;
81                   else
82                      bitmap.pixelFormat = pixelFormat565;
83                   break;
84                case 32:
85                   bitmap.pixelFormat = pixelFormat888; break;
86                default:
87                   validFormat = false;
88                   break;
89             }
90
91             if(validFormat)
92             {
93                bitmap.picture = (byte *)backDesc.lpSurface;
94                bitmap.stride = backDesc.lPitch;
95                bitmap.stride >>= GetColorDepthShifts(bitmap.pixelFormat);
96                bitmap.size = bitmap.stride * bitmap.height;
97                result = true;
98             }
99             else
100                Unlock();
101          }
102       }
103       return result;
104    }
105 };
106
107 static HDC tmpDC;
108 /*
109 static byte defaultRGBLookup[32768];
110 static bool rgbLookupSet = false;
111 */
112 // #define USE_GDI_FONT
113
114 static bool CALLBACK DeviceCallBack(GUID FAR * guid, char * description, char * driverName, IDirectDraw ** directDraw)
115 {
116    if(!DirectDrawCreate( guid, directDraw, null ))
117       return false;
118    return true;
119 }
120
121 class DirectDrawDisplayDriver : DisplayDriver
122 {
123    class_property(name) = "DirectDraw";
124
125    void ReleaseSurface(Display display, Surface surface)
126    {
127       DDrawDisplay ddrawDisplay = display.driverData;
128       ((subclass(DisplayDriver))class(LFBDisplayDriver)).ReleaseSurface(display, surface);
129       ddrawDisplay.Unlock();
130       IDirectDrawSurface_ReleaseDC(ddrawDisplay.back, ddrawDisplay.hdc);
131       ddrawDisplay.hdc = null;
132    }
133
134    bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
135    {
136       DDrawDisplay ddrawDisplay = display.driverData;
137       LFBSurface lfbSurface;
138       bool result = false;
139       {
140          if((surface.driverData = lfbSurface = LFBSurface { }))
141          {
142             surface.offset.x = x;
143             surface.offset.y = y;
144             //surface.unclippedBox = surface.box = clip;
145
146             ddrawDisplay.Lock();
147             IDirectDrawSurface_GetDC(ddrawDisplay.back, &ddrawDisplay.hdc);
148             result = ((subclass(DisplayDriver))class(LFBDisplayDriver)).GetSurface(display, surface, x, y, clip);
149          }
150       }
151       return result;
152    }
153
154    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
155    {
156       return ((subclass(DisplayDriver))class(LFBDisplayDriver)).GetBitmapSurface(displaySystem, surface, bitmap, x, y, clip);
157    }
158
159    void Clip(Display display, Surface surface, Box clip)
160    {
161       ((subclass(DisplayDriver))class(LFBDisplayDriver)).Clip(display, surface, clip);
162    }
163
164    void DestroyDisplay(Display display)
165    {
166       DDrawDisplay ddrawDisplay = display.driverData;
167       IDirectDraw * directDraw = ddrawDisplay.directDraw;
168
169       if(ddrawDisplay.back)
170          IDirectDrawSurface_Release(ddrawDisplay.back);
171       if(ddrawDisplay.front)
172          IDirectDrawSurface_Release(ddrawDisplay.front);
173       if(ddrawDisplay.palette)
174          IDirectDrawPalette_Release(ddrawDisplay.palette);
175
176       if(directDraw)
177       {
178          IDirectDraw_SetCooperativeLevel(directDraw, display.window, DDSCL_NORMAL );
179       }
180
181       if(display)
182          ((subclass(DisplayDriver))class(LFBDisplayDriver)).DestroyDisplay(display);
183
184       if(directDraw)
185       {
186          if(display.displaySystem.flags.fullScreen)
187             IDirectDraw_RestoreDisplayMode(directDraw);
188          IDirectDraw_Release(directDraw);
189       }
190
191       delete ddrawDisplay;
192       display.driverData = null;
193    }
194
195    void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
196    {
197       DDrawDisplay ddrawDisplay = display.driverData;
198       IDirectDraw * directDraw = ddrawDisplay.directDraw;
199       if(ddrawDisplay.bitmap.pixelFormat == pixelFormat8)
200       {
201          int c;
202          ColorAlpha realPalette[256];
203          PALETTEENTRY ddPalette[256];
204          int reserved = (display.displaySystem.flags.fullScreen) ? 0 : 10;
205
206          if(reserved)
207          {
208             HDC hdc = GetDC(display.window);
209             GetSystemPaletteEntries(hdc,0,256,(PALETTEENTRY *)realPalette);
210             for(c=0; c<256; c++)
211                realPalette[c] = ColorAlpha { 255, { realPalette[c].color.b, realPalette[c].color.g, realPalette[c].color.r } };
212             ReleaseDC(display.window,hdc);
213
214             // *** Reserved Palette Handling ***
215             if(!palette)
216             {
217                palette = GetDefaultPalette();
218                CopyBytesBy4(realPalette+reserved,palette+reserved,256-2*reserved);
219                /*
220                if(!rgbLookupSet)
221                   for(c = 0; c<32768; c++)
222                      defaultRGBLookup[c] = (byte)BestColorMatch(realPalette, 0, 255, (Color555)c);
223                rgbLookupSet = true;
224                */
225                CopyBytes(ddrawDisplay.rgbLookup, defaultRGBLookup, 32768);
226                for(c=0; c<256; c++)
227                {
228                   int i;
229                   for(i=0; i<LIGHTSTEPS; i++)
230                   {
231                      ddrawDisplay.lightTable[c][i]=ddrawDisplay.rgbLookup[
232                         (uint16)(Color555)
233                            Color {
234                                 (byte)(((uint16)realPalette[c].color.r*i) >>LIGHTSHIFT),
235                                 (byte)(((uint16)realPalette[c].color.g*i) >>LIGHTSHIFT),
236                                 (byte)(((uint16)realPalette[c].color.b*i) >>LIGHTSHIFT) }];
237                   }
238                }
239                CopyBytesBy4(ddrawDisplay.bitmap.palette, realPalette, 256);
240             }
241             else
242             {
243                CopyBytesBy4(realPalette+reserved,palette+reserved,256-2*reserved);
244                ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetPalette(display, realPalette, colorMatch);
245             }
246          }
247          else
248             ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetPalette(display, palette, colorMatch);
249          // *********************************
250
251          for (c = 0; c<reserved; c++)
252          {
253             ddPalette[c].peFlags = PC_EXPLICIT;
254             ddPalette[c].peRed = (byte)c;
255             ddPalette[c].peGreen = 0;
256             ddPalette[c].peBlue = 0;
257
258             ddPalette[c+256-reserved].peFlags = PC_EXPLICIT;
259             ddPalette[c+256-reserved].peRed = (byte)(c+256-reserved);
260             ddPalette[c+256-reserved].peGreen = 0;
261             ddPalette[c+256-reserved].peBlue = 0;
262          }
263          for(c = reserved; c < 256 - reserved; c++)
264          {
265             ddPalette[c].peFlags = PC_NOCOLLAPSE;
266             ddPalette[c].peRed = ddrawDisplay.bitmap.palette[c].color.r;
267             ddPalette[c].peGreen = ddrawDisplay.bitmap.palette[c].color.g;
268             ddPalette[c].peBlue = ddrawDisplay.bitmap.palette[c].color.b;
269          }
270
271          if(!ddrawDisplay.palette)
272          {
273             IDirectDraw_CreatePalette(directDraw, DDPCAPS_8BIT, ddPalette, &ddrawDisplay.palette, null);
274             IDirectDrawSurface_SetPalette(ddrawDisplay.front, ddrawDisplay.palette);
275          }
276          else
277             IDirectDrawPalette_SetEntries(ddrawDisplay.palette,0,0,256,ddPalette);
278       }
279       else
280          ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetPalette(display, palette, colorMatch);
281    }
282
283    bool CreateDisplaySystem(DisplaySystem displaySystem)
284    {
285       bool result = false;
286       displaySystem.flags.memBackBuffer = true;
287       tmpDC = GetDC(0);
288       result = true;
289       return result;
290    }
291
292    void DestroyDisplaySystem(DisplaySystem displaySystem)
293    {
294       ReleaseDC(0, tmpDC);
295    }
296
297    bool DisplaySize(Display display, int width, int height)
298    {
299       DDrawDisplay ddrawDisplay = display.driverData;
300       bool result = false;
301       IDirectDraw * directDraw = ddrawDisplay.directDraw;
302
303       if(ddrawDisplay.back)
304          IDirectDrawSurface_Release(ddrawDisplay.back);
305
306       ddrawDisplay.backDesc.dwFlags        = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
307       ddrawDisplay.backDesc.dwWidth        = width;
308       ddrawDisplay.backDesc.dwHeight       = height;
309       ddrawDisplay.backDesc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; // = DDSCAPS_OFFSCREENPLAIN;
310       //ddrawDisplay.backDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
311
312       if(!IDirectDraw_CreateSurface(directDraw, &ddrawDisplay.backDesc, &ddrawDisplay.back, null))
313       {
314          IDirectDrawClipper * clipper;
315          if(!IDirectDraw_CreateClipper(directDraw, 0, &clipper, null))
316          {
317             IDirectDrawClipper_SetHWnd(clipper, 0, display.window);
318             IDirectDrawSurface_SetClipper(ddrawDisplay.front, clipper);
319             IDirectDrawClipper_Release(clipper);
320
321             // Set up format by locking / unlocking
322             if(ddrawDisplay.Lock())
323             {
324                display.displaySystem.pixelFormat = ddrawDisplay.bitmap.pixelFormat;
325                ddrawDisplay.Unlock();
326                result = true;
327             }
328          }
329       }
330
331       ((subclass(DisplayDriver))class(LFBDisplayDriver)).DisplaySize(display, width, height);
332
333       display.width = width;
334       display.height = height;
335
336       return result;
337    }
338
339    bool CreateDisplay(Display display)
340    {
341       bool result = false;
342       DDrawDisplay ddrawDisplay = display.driverData = DDrawDisplay { };
343       if(ddrawDisplay)
344       {
345          IDirectDraw * directDraw = null;
346          DirectDrawEnumerateA(DeviceCallBack, &directDraw);
347          if(directDraw)
348          {
349             DirectDrawCreate(null, &directDraw, null);
350             ddrawDisplay.directDraw = directDraw;
351             if(((subclass(DisplayDriver))class(LFBDisplayDriver)).CreateDisplay(display))
352             {
353                ddrawDisplay.frontDesc.dwSize = ddrawDisplay.backDesc.dwSize = sizeof(DDSURFACEDESC);
354
355                if(!IDirectDraw_SetCooperativeLevel( directDraw, display.window,
356                   (display.displaySystem.flags.fullScreen) ? (DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN) : DDSCL_NORMAL))
357                {
358                   ddrawDisplay.frontDesc.dwFlags = DDSD_CAPS;
359                   ddrawDisplay.frontDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
360                   if(!IDirectDraw_CreateSurface( directDraw, &ddrawDisplay.frontDesc, &ddrawDisplay.front, null ))
361                   {
362                      // To find out the format...
363                      DisplaySize(display, 1, 1);
364                      result = true;
365                   }
366                }
367             }
368          }
369       }
370       return result;
371    }
372
373    void DisplayPosition(Display display, int x, int y)
374    {
375       ((subclass(DisplayDriver))class(LFBDisplayDriver)).DisplayPosition(display, x, y);
376    }
377
378    void RestorePalette(Display display)
379    {
380       DDrawDisplay ddrawDisplay = display.driverData;
381       IDirectDrawSurface_SetPalette(ddrawDisplay.front, ddrawDisplay.palette);
382    }
383
384    void StartUpdate(Display display)
385    {
386       DDrawDisplay ddrawDisplay = display.driverData;
387       ddrawDisplay.Unlock();
388    }
389
390    void EndUpdate(Display display)
391    {
392       DDrawDisplay ddrawDisplay = display.driverData;
393       ddrawDisplay.Lock();
394    }
395
396    void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
397    {
398    }
399
400    void Update(Display display, Box updateBox)
401    {
402       DDrawDisplay ddrawDisplay = display.driverData;
403
404       // TODO: (Compiler) Shouldn't &updateBox be the same as updateBox in this assignment?
405       Box * box = updateBox; // ? updateBox : &ddrawDisplay.updateBox;
406       RECT r, br;
407
408       r.left  = ddrawDisplay.x + box->left;
409       r.top   = ddrawDisplay.y + box->top;
410       r.right = ddrawDisplay.x + box->right+1;
411       r.bottom= ddrawDisplay.y + box->bottom+1;
412
413       br.left  = box->left;
414       br.top   = box->top;
415       br.right = box->right+1;
416       br.bottom= box->bottom+1;
417
418       if(r.right > r.left && r.bottom > r.top)
419       {
420          if(IDirectDrawSurface_Blt(ddrawDisplay.front, &r, ddrawDisplay.back, &br, DDBLT_WAIT,null) == DDERR_SURFACELOST)
421          {
422             IDirectDrawSurface_Restore(ddrawDisplay.front);
423             IDirectDrawSurface_Blt(ddrawDisplay.front, &r, ddrawDisplay.back, &br, DDBLT_WAIT,null);
424          }
425       }
426       // ((subclass(DisplayDriver))class(LFBDisplayDriver)).DisplayScreen(display, updateBox);
427    }
428
429    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
430    {
431       bool result = false;
432       DDrawDisplay ddrawDisplay = display.driverData;
433       if(ddrawDisplay.Lock())
434       {
435          display.displaySystem.pixelFormat = ddrawDisplay.bitmap.pixelFormat;
436          result = ((subclass(DisplayDriver))class(LFBDisplayDriver)).GrabScreen(display, bitmap, x,y, w,h);
437          ddrawDisplay.Unlock();
438       }
439       return result;
440    }
441
442    bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
443    {
444       return ((subclass(DisplayDriver))class(LFBDisplayDriver)).MakeDDBitmap(displaySystem, bitmap, mipMaps);
445    }
446
447    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
448    {
449       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FreeBitmap(displaySystem, bitmap);
450    }
451
452    void SetForeground(Display display, Surface surface, ColorAlpha color)
453    {
454    #ifdef USE_GDI_FONT
455       DDrawDisplay ddrawDisplay = display.driverData;
456       SetTextColor(ddrawDisplay.hdc, RGB(color.color.r, color.color.g, color.color.b));
457    #endif
458       ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetForeground(display, surface, color);
459    }
460
461    void SetBackground(Display display, Surface surface, ColorAlpha color)
462    {
463    #ifdef USE_GDI_FONT
464       DDrawDisplay ddrawDisplay = display.driverData;
465       COLORREF rgb;
466
467       if(ddrawDisplay.bitmap.pixelFormat == pixelFormat8)
468          color = ddrawDisplay.bitmap.palette[ddrawDisplay.rgbLookup[(uint16)(Color555) color]];
469       rgb = RGB(color.color.r, color.color.g, color.color.b);
470       SetBkColor(ddrawDisplay.hdc, rgb);
471    #endif
472       ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetBackground(display, surface, color);
473    }
474
475    ColorAlpha GetPixel(Display display, Surface surface,int x,int y)
476    {
477       return 0;
478    }
479
480    void PutPixel(Display display, Surface surface, int x, int y)
481    {
482       ((subclass(DisplayDriver))class(LFBDisplayDriver)).PutPixel(display, surface, x,y);
483    }
484
485    void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
486    {
487       ((subclass(DisplayDriver))class(LFBDisplayDriver)).DrawLine(display, surface, x1,y1,x2,y2);
488    }
489
490    void Rectangle(Display display, Surface surface, int x1, int y1, int x2, int y2)
491    {
492       ((subclass(DisplayDriver))class(LFBDisplayDriver)).Rectangle(display, surface, x1,y1,x2,y2);
493    }
494
495    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
496    {
497       ((subclass(DisplayDriver))class(LFBDisplayDriver)).Area(display, surface, x1,y1,x2,y2);
498    }
499
500    void Clear(Display display, Surface surface, ClearType flags)
501    {
502       ((subclass(DisplayDriver))class(LFBDisplayDriver)).Clear(display, surface, flags);
503    }
504
505    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
506    {
507       return ((subclass(DisplayDriver))class(LFBDisplayDriver)).ConvertBitmap(displaySystem, src, format, palette);
508    }
509
510    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
511    {
512       return ((subclass(DisplayDriver))class(LFBDisplayDriver)).AllocateBitmap(displaySystem, bitmap, width, height, stride, format, allocatePalette);
513    }
514
515    void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
516    {
517       ((subclass(DisplayDriver))class(LFBDisplayDriver)).Blit(display, surface, src, dx, dy, sx, sy, w, h);
518    }
519
520    void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
521    {
522       ((subclass(DisplayDriver))class(LFBDisplayDriver)).Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
523    }
524
525    void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
526    {
527       ((subclass(DisplayDriver))class(LFBDisplayDriver)).Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
528    }
529
530    void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
531    {
532       ((subclass(DisplayDriver))class(LFBDisplayDriver)).Blit(display, surface, src, dx, dy, sx, sy, w, h);
533    }
534
535    void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
536    {
537       ((subclass(DisplayDriver))class(LFBDisplayDriver)).Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
538    }
539
540    void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
541    {
542       Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
543    }
544
545    void TextFont(Display display, Surface surface, Font font)
546    {
547    #ifdef USE_GDI_FONT
548       DDrawDisplay ddrawDisplay = display.driverData;
549       /*if(display.alphaBlend)
550       {
551          if(!gdiFont.font)
552          {
553             gdiFont.font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(display.displaySystem,
554                gdiFont.faceName, gdiFont.size, gdiFont.flags);
555          }
556          ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, gdiFont.font);
557       }
558       else */
559          SelectObject(ddrawDisplay.hdc, font);
560    #else
561       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
562       SetForeground(display, surface, surface.foreground);
563    #endif
564    }
565
566    void TextOpacity(Display display, Surface surface, bool opaque)
567    {
568    #ifdef USE_GDI_FONT
569       DDrawDisplay ddrawDisplay = display.driverData;
570       SetBkMode(ddrawDisplay.hdc, surface.textOpacity ? OPAQUE : TRANSPARENT);
571    #else
572       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextOpacity(display, surface, opaque);
573    #endif
574    }
575
576    Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
577    {
578    #ifdef USE_GDI_FONT
579       void * font;
580       HDC hdc = GetDC(null);
581       font = CreateFont(-(int)((float)size * GetDeviceCaps(hdc, LOGPIXELSY) / 72 + 0.5),
582          0,0,0, (flags.bold) ? FW_BOLD : FW_NORMAL, flags.italic,
583             flags.underline,0,DEFAULT_CHARSET,
584                         OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
585                         DEFAULT_PITCH|FF_DONTCARE,faceName);
586       ReleaseDC(null, hdc);
587       return font;
588    #else
589       Font font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
590       /*if(font)
591       {
592          font.bitmap.pixelFormat = C8;
593          font.bitmap.transparent = true;
594          font.bitmap.allocatePalette = false;
595          delete font.bitmap.palette;
596          font.bitmap.shadeShift = 8-LIGHTSHIFT;
597
598          // Tune the bitmap a bit until we decide to do alpha blending...
599          {
600             Bitmap bitmap = font.bitmap;
601             int x,y;
602             for(y = 0; y<bitmap.height; y++)
603             {
604                byte * picture = bitmap.picture + bitmap.stride * y;
605                for(x = 0; x<bitmap.width; x++, picture++)
606                {
607                   if(*picture > 100)
608                      *picture = Max(*picture, 150);
609                   else
610                      *picture = 0;
611                }
612             }
613          }
614          {
615             LFBDisplay lfbDisplay = display.driverData;
616             if(lfbDisplay)
617                font.bitmap.palette = lfbDisplay.bitmap.palette;
618             else
619                font.bitmap.palette = GetDefaultPalette();
620          }
621       }*/
622       return font;
623    #endif
624    }
625
626    void UnloadFont(DisplaySystem displaySystem, Font font)
627    {
628    #ifdef USE_GDI_FONT
629       if(font)
630          DeleteObject(font);
631    #else
632       ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
633    #endif
634    }
635
636    void WriteText(Display display, Surface surface, int x, int y, const char * text, int len, int prevGlyph, int * rPrevGlyph)
637    {
638    #ifdef USE_GDI_FONT
639       DDrawDisplay ddrawDisplay = display.driverData;
640
641       /*if(display.alphaBlend)
642       {
643          GDIFont gdiFont = (GDIFont)surface.font;
644          if(!gdiFont.font)
645          {
646             gdiFont.font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(display.displaySystem,
647                gdiFont.faceName, gdiFont.size, gdiFont.flags);
648          }
649          if(surface.textOpacity)
650          {
651             int w, h;
652             ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(display.displaySystem, gdiFont.font, text, len, &w, &h);
653             Area(display, surface, x, y, x+w-1, y+h-1);
654          }
655          ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len);
656       }
657       else*/
658       {
659          int wordCount;
660          uint16 * u16text = UTF8toUTF16Len(text, len, &wordCount);
661
662          TextOut(ddrawDisplay.hdc, x + surface.offset.x, y + surface.offset.y, u16text, wordCount);
663          if(display.alphaBlend)
664          {
665             int w, h, oh;
666             FontExtent(display.displaySystem, surface.font, text, len, &w, &h, prevGlyph, rPrevGlyph, &oh);
667             w += oh;
668             surface.writeColor = false;
669             SetBackground(display, surface, surface.foreground);
670             Area(display, surface,x-2,y-2,x+w+1,y+h+1);
671             SetBackground(display, surface, surface.background);
672             surface.writeColor = true;
673          }
674          delete u16text;
675       }
676       /*
677       TextOut(ddrawDisplay.hdc, x+surface.offset.x,y+surface.offset.y, text,len);
678       */
679    #else
680       if(surface.textOpacity)
681       {
682          int w, h, adv;
683          ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(display.displaySystem, surface.font, text, len, &w, &h, prevGlyph, rPrevGlyph, &adv);
684          w += adv;
685          Area(display, surface, x, y, x+w-1, y+h-1);
686       }
687       ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x,y, text, len, prevGlyph, rPrevGlyph);
688    #endif
689    }
690
691    void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
692    {
693    #ifdef USE_GDI_FONT
694       if(false) //display.alphaBlend)
695         ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
696       else
697       {
698          if(tmpDC)
699          {
700             SelectObject(tmpDC, font);
701             TextExtent(null, null, text, len, width, height);
702          }
703          else
704          {
705             if(width) *width = 0;
706             if(height) *height = 0;
707             if(adv) *adv = 0;
708          }
709       }
710       /*
711       HDC hdc = tmpDC;
712       SIZE space, size;
713       uint realLen;
714
715       SelectObject(hdc, font);
716       for(realLen = 0; realLen<len && text[realLen]; realLen++);
717       GetTextExtentPoint32(hdc," ",1,&space);
718       GetTextExtentPoint32(hdc,text,realLen,&size);
719
720       if(width) *width = size.cx + (len - realLen) * space.cx;
721       if(height)
722       {
723          if(realLen)
724             *height = size.cy;
725          else
726             *height = len ? space.cy : 0;
727       }
728       */
729    #else
730       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
731    #endif
732    }
733
734    void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
735    {
736    #ifdef USE_GDI_FONT
737       /*if(display && display.alphaBlend)
738          ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextExtent(display, surface, text, len, prevGlyph, rPrevGlyph, width, height, adv);
739       else*/
740
741       {
742          DDrawDisplay ddrawDisplay = display ? display.driverData : null;
743          HDC hdc = ddrawDisplay ? ddrawDisplay.hdc : tmpDC;
744          SIZE space, size;
745          uint realLen;
746          int wordCount;
747          uint16 * u16text = UTF8toUTF16Len(text, len, &wordCount);
748
749          for(realLen = 0; realLen<wordCount && u16text[realLen]; realLen++);
750          GetTextExtentPoint32A(hdc, " ", 1, &space);
751          GetTextExtentPoint32(hdc, u16text, realLen, &size);
752          delete u16text;
753
754          // UNICODE FIX: proper space computation
755          if(width) *width = size.cx + (wordCount - realLen) * space.cx;
756          if(adv) *adv = 0;
757          if(height)
758          {
759             if(realLen)
760                *height = size.cy;
761             else
762                *height = wordCount ? space.cy : 0;
763          }
764       }
765    /*
766       HDC hdc = ddrawDisplay.hdc;
767       SIZE space, size;
768       uint realLen;
769
770       for(realLen = 0; realLen<len && text[realLen]; realLen++);
771       GetTextExtentPoint32(hdc," ",1,&space);
772       GetTextExtentPoint32(hdc,text,realLen,&size);
773
774       if(width) *width = size.cx + (len - realLen) * space.cx;
775       if(height)
776       {
777          if(realLen)
778             *height = size.cy;
779          else
780             *height = len ? space.cy : 0;
781       }
782       */
783    #else
784       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextExtent(display, surface, text, len, width, height, prevGlyph, rPrevGlyph, adv);
785    #endif
786    }
787
788    void DrawingChar(Display display, Surface surface, byte character)
789    {
790
791    }
792
793    void LineStipple(Display display, Surface surface, uint stipple)
794    {
795       ((subclass(DisplayDriver))class(LFBDisplayDriver)).LineStipple(display, surface, stipple);
796    }
797
798    bool Lock(Display display)
799    {
800       /*DDrawDisplay ddrawDisplay = display.driverData;
801       if(ddrawDisplay.Lock())
802       {
803          display.displaySystem.pixelFormat = ddrawDisplay.bitmap.pixelFormat;
804          IDirectDrawSurface_GetDC(ddrawDisplay.back, &ddrawDisplay.hdc);
805       }*/
806       return true;
807    }
808
809    void Unlock(Display display)
810    {
811       /*DDrawDisplay ddrawDisplay = display.driverData;
812       IDirectDrawSurface_ReleaseDC(ddrawDisplay.back, ddrawDisplay.hdc);
813       ddrawDisplay.Unlock();   */
814    }
815 }
816
817 #endif