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