compiler: More compatible handling of stdint.h inclusion
[sdk] / ecere / src / gfx / drivers / Win32PrinterDisplayDriver.ec
1 namespace gfx::drivers;
2
3 import "instance"
4
5 #if defined(__WIN32__)
6
7 #undef _WIN32_WINNT
8 #define _WIN32_WINNT 0x0500
9 #define WIN32_LEAN_AND_MEAN
10 #define UNICODE
11 #define Method _Method
12 #define String _String
13 #include <windows.h>
14 #include <winspool.h>
15 #undef Method
16 #undef String
17
18 default wchar_t *wcstok(wchar_t *strToken,const wchar_t *strDelimit);
19
20 import "Display"
21
22 //static char szMessage[]= L"Printing ECERE Document...";
23 static char szMessage[]= "Printing ECERE Document...";
24
25 /*
26 static define RESX = 850;
27 static define RESY = 1100;
28 */
29
30 class Win32PrinterDisplay : struct
31 {
32    HPALETTE palette;
33    LOGPALETTE * logPalette;
34    Point offset;
35    int width, height;
36    bool completed;
37
38    HDC hdc;
39    HRGN rgn;
40    RGNDATA * data;
41
42    ~Win32PrinterDisplay()
43    {
44       //if(memDC) DeleteDC(memDC);
45       //if(memBitmap) DeleteObject(memBitmap); 
46       if(palette) DeleteObject(palette);
47       delete logPalette;
48    }
49 };
50 /*
51 static byte defaultRGBLookup[32768];
52 static bool rgbLookupSet = false;
53 */
54 class Win32PrinterSystem : struct
55 {
56    HDC hdc;
57    HDC tmpDC, bmpDC;
58    int depth;
59    int resX, resY;   // Save the display here, support only one display at a time
60
61    ~Win32PrinterSystem()
62    {
63
64    }
65 };
66
67 class Win32PrinterSurface : struct
68 {
69    HDC hdc;
70    HRGN rgn, clippedRgn;
71    COLORREF color, backColor;
72
73    Point offset;
74    Box box, unclippedBox;
75 };
76
77 class Win32PrinterBitmap : struct
78 {
79    HBITMAP bmp, mask;
80    HDC memDC;
81 };
82
83 static PixelFormat GetColorFormat(int depth)
84 {
85    if(depth == 8) 
86       return pixelFormat8;
87    else if(depth == 16) 
88       return pixelFormat555;
89    else 
90       return pixelFormat888;
91 }
92
93 class Win32PrinterDisplayDriver : DisplayDriver
94 {
95    class_property(name) = "Win32Printer";
96    class_property(printer) = bool::true;
97
98    bool CreateDisplaySystem(DisplaySystem displaySystem)
99    {
100       Win32PrinterSystem gdiSystem = displaySystem.driverData = Win32PrinterSystem { };
101       return true; //false;
102    }
103
104    void DestroyDisplaySystem(DisplaySystem displaySystem)
105    {
106       Win32PrinterSystem gdiSystem = displaySystem.driverData;
107       DeleteDC(gdiSystem.tmpDC);
108       DeleteDC(gdiSystem.bmpDC);
109       DeleteDC(gdiSystem.hdc);
110       displaySystem.driverData = null;
111       delete gdiSystem;
112    }
113
114    void DestroyDisplay(Display display)
115    {
116       Win32PrinterSystem gdiSystem = display.displaySystem.driverData;
117       Win32PrinterDisplay gdiDisplay = display.driverData;
118       if(gdiDisplay)
119       {
120                 EndPage(gdiDisplay.hdc);
121          Escape(gdiDisplay.hdc, ENDDOC, 0, null, null);
122       }
123
124       // ((subclass(DisplayDriver))class(LFBDisplayDriver)).DestroyDisplay(display);
125       delete gdiDisplay;
126       display.driverData = null;
127
128       if(gdiSystem)
129       {
130          DeleteDC(gdiSystem.tmpDC);
131          DeleteDC(gdiSystem.bmpDC);
132          DeleteDC(gdiSystem.hdc);
133       }
134    }
135
136    void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
137    {
138       Win32PrinterDisplay gdiDisplay = display.driverData;
139       if(display.displaySystem.pixelFormat == pixelFormat8)
140       {
141          int c;
142          ColorAlpha realPalette[256];
143          int reserved = (display.flags.fullScreen) ? 1 : 10;
144          HDC hdc = gdiDisplay.hdc;
145          if(hdc)
146          {
147             //if(reserved > 1)
148             {
149                GetSystemPaletteEntries(hdc,0,256,(PALETTEENTRY *)realPalette);
150                for(c = 0; c<256; c++)
151                   realPalette[c] = RGB(realPalette[c].color.r, realPalette[c].color.g, realPalette[c].color.b);
152
153                // *** Reserved Palette Handling ***
154                /*if(!palette)
155                {
156                   palette = GetDefaultPalette();
157                   CopyBytesBy4(realPalette+reserved,palette+reserved,256-2*reserved);
158                   if(!rgbLookupSet)
159                      for(c = 0; c<32768; c++)
160                         defaultRGBLookup[c] = (byte)BestColorMatch(realPalette, 1,255, (Color555)c);
161                   rgbLookupSet = true;
162                   CopyBytes(gdiDisplay.rgbLookup, defaultRGBLookup, 32768);
163                   for(c=0; c<256; c++)
164                   {
165                      int i;
166                      for(i=0; i<LIGHTSTEPS; i++)
167                      {
168                         gdiDisplay.lightTable[c][i]=gdiDisplay.rgbLookup[(uint16)Color555 {
169                                 (byte)(((uint16)realPalette[c].color.r*i) >> LIGHTSHIFT),
170                                 (byte)(((uint16)realPalette[c].color.g*i) >> LIGHTSHIFT),
171                                 (byte)(((uint16)realPalette[c].color.b*i) >> LIGHTSHIFT) }];
172                      }
173                   }
174                   CopyBytesBy4(gdiDisplay.bitmap.palette, realPalette, 256);
175                }
176                else
177                */
178                {
179                   CopyBytesBy4(realPalette+reserved,palette+reserved,256-2*reserved);
180                   // ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetPalette(display, realPalette, colorMatch);
181                }
182             }
183             /*else
184                ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetPalette(display, palette, colorMatch);*/
185             // *********************************
186
187             gdiDisplay.logPalette->palVersion = 0x300;
188             gdiDisplay.logPalette->palNumEntries = 256;
189
190             for(c = 0; c < 256; c++)
191             {
192                gdiDisplay.logPalette->palPalEntry[c].peFlags = PC_NOCOLLAPSE;
193                gdiDisplay.logPalette->palPalEntry[c].peRed   = realPalette[c].color.r;
194                gdiDisplay.logPalette->palPalEntry[c].peGreen = realPalette[c].color.g;
195                gdiDisplay.logPalette->palPalEntry[c].peBlue  = realPalette[c].color.b;
196             }
197
198             if(!gdiDisplay.palette)
199                gdiDisplay.palette = CreatePalette(gdiDisplay.logPalette);
200             else
201                SetPaletteEntries(gdiDisplay.palette, 0, 256, gdiDisplay.logPalette->palPalEntry);
202
203             SelectPalette(hdc, gdiDisplay.palette, FALSE);
204             RealizePalette(hdc);
205
206             // SetDIBColorTable(gdiDisplay.hdc, 0, 256, (RGBQUAD *)gdiDisplay.bitmap.palette);
207          }
208       }
209    }
210
211    bool CreateDisplay(Display display)
212    {
213       Win32PrinterSystem gdiSystem = display.displaySystem.driverData;
214       bool result = false;
215
216       if(display)
217       {
218          Win32PrinterDisplay gdiDisplay = display.driverData = Win32PrinterDisplay { };
219          if((gdiDisplay.logPalette = (LOGPALETTE *)new0 byte[sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*256]) /*&&
220             ((subclass(DisplayDriver))class(LFBDisplayDriver)).CreateDisplay(display)*/)
221          {
222             result = true;
223          }
224       }
225       return result;
226    }
227
228    bool DisplaySize(Display display, int width, int height)
229    {
230       Win32PrinterSystem gdiSystem = display.displaySystem.driverData;
231       Win32PrinterDisplay gdiDisplay = display.driverData;
232       bool result = false;
233       HDC hdc = gdiSystem.hdc;
234
235       if(!width || !height)
236          result = true;
237       else
238       {
239          if(!hdc)
240          {
241                 uint16 szPrinter[160];
242                 uint16 *szDevice, *szDriver, *szOutput;
243
244             GetProfileString(L"windows", L"device", L"...", (char *)szPrinter, 160);
245                 szDevice = wcstok(szPrinter, L",");
246                 szDriver = wcstok(null,      L",");
247                 szOutput = wcstok(null,      L",");
248             if(szDevice && szDriver && szOutput)
249             {
250                DEVMODE * devMode = null;
251                HANDLE hPrinter = null;
252                uint size;
253                OpenPrinter(szPrinter, &hPrinter, null);
254                size = DocumentProperties(null, hPrinter, szDevice, null, null, 0);
255                devMode = (DEVMODE *)new0 byte[size];
256                DocumentProperties(null, hPrinter, szDevice, devMode, null, DM_OUT_BUFFER);
257                devMode->dmOrientation = (width > height) ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;
258                DocumentProperties(null, hPrinter, szDevice, devMode, devMode, DM_IN_BUFFER|DM_OUT_BUFFER);
259                gdiSystem.hdc = CreateDC(szDriver, szDevice, szOutput, devMode);
260                delete devMode;
261                ClosePrinter(hPrinter);
262                if(gdiSystem.hdc)
263                {
264                   gdiSystem.tmpDC = CreateCompatibleDC(gdiSystem.hdc);
265                   gdiSystem.bmpDC = CreateCompatibleDC(gdiSystem.hdc);
266                   gdiSystem.depth = GetDeviceCaps(gdiSystem.hdc, BITSPIXEL);
267                   gdiSystem.depth = 32;
268                   display.displaySystem.pixelFormat = GetColorFormat(gdiSystem.depth);
269
270                   /*
271                   SetMapMode(gdiSystem.hdc, MM_ANISOTROPIC);
272                   SetWindowExtEx(gdiSystem.hdc, RESX, RESY, null);
273                   SetViewportExtEx(gdiSystem.hdc, GetDeviceCaps(gdiSystem.hdc, HORZRES), GetDeviceCaps(gdiSystem.hdc, VERTRES), null);
274                   */
275                   SetMapMode(gdiSystem.hdc, MM_TEXT);
276
277                   {
278                      String docName = printingDocumentName ? printingDocumentName : szMessage;
279                      char curDir[MAX_LOCATION];
280                      GetWorkingDir(curDir, MAX_LOCATION);
281
282                      if(Escape(gdiSystem.hdc, STARTDOC, strlen(docName), docName, null ) > 0)
283                         {
284                                 StartPage(gdiSystem.hdc);
285                         result = true;
286                      }
287                      ChangeWorkingDir(curDir);
288                   }
289                }
290                //displaySystem.flags.memBackBuffer = true;
291             }
292          }
293          hdc = gdiSystem.hdc;
294          gdiDisplay.hdc = gdiSystem.hdc;
295         gdiDisplay.width = GetDeviceCaps(hdc, HORZRES);
296         gdiDisplay.height = GetDeviceCaps(hdc, VERTRES);
297
298          gdiSystem.resX = display.width = width;
299          gdiSystem.resY = display.height = height;
300
301          SelectObject(gdiDisplay.hdc,GetStockObject(DC_PEN));
302          SelectObject(gdiDisplay.hdc,GetStockObject(DC_BRUSH));
303          SetBkMode(gdiDisplay.hdc, TRANSPARENT);
304          result = true;
305       }
306       return result;
307    }
308
309    void DisplayPosition(Display display, int x, int y)
310    {
311       Win32PrinterDisplay gdiDisplay = display.driverData;
312       gdiDisplay.offset.x = x;
313       gdiDisplay.offset.y = y;
314
315    }
316
317    void RestorePalette(Display display)
318    {
319       Win32PrinterDisplay gdiDisplay = display.driverData;
320       HDC hdc = gdiDisplay.hdc;
321       if(hdc)
322       {
323          if(gdiDisplay.palette)
324          {
325             SelectPalette(hdc, gdiDisplay.palette, FALSE);
326             RealizePalette(hdc);
327          }
328       }
329    }
330
331    #define MAX_EXPOSED  50
332
333    void StartUpdate(Display display)
334    {
335       Win32PrinterDisplay gdiDisplay = display.driverData;
336       if(gdiDisplay && !gdiDisplay.completed)
337       {
338          GdiSetBatchLimit(1000);
339
340          gdiDisplay.rgn = CreateRectRgn(0,0,0,0);
341          gdiDisplay.data = (RGNDATA *) new0 byte[sizeof(RGNDATAHEADER) + sizeof(RECT) * MAX_EXPOSED];
342          if(gdiDisplay.palette)
343             SelectPalette(gdiDisplay.hdc, gdiDisplay.palette, FALSE);
344       }
345    }
346
347    void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
348    {
349
350    }
351
352    void Update(Display display, Box updateBox)
353    {
354
355    }
356
357    void EndUpdate(Display display)
358    {
359       Win32PrinterDisplay gdiDisplay = display.driverData;
360       if(gdiDisplay && !gdiDisplay.completed)
361       {
362          DeleteObject(gdiDisplay.rgn);
363          delete gdiDisplay.data;
364          gdiDisplay.data = null;
365          gdiDisplay.completed = true;
366       }
367    }
368
369    void NextPage(Display display)
370    {
371       Win32PrinterDisplay gdiDisplay = display.driverData;
372       gdiDisplay.completed = false;
373       EndPage(gdiDisplay.hdc);
374       StartPage(gdiDisplay.hdc);      
375    }
376
377    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
378    {
379       // (((subclass(DisplayDriver))class(LFBDisplayDriver)).FreeBitmap(displaySystem, bitmap);
380       Win32PrinterBitmap gdiBitmap = bitmap.driverData;
381
382       if(gdiBitmap.memDC)
383          DeleteDC(gdiBitmap.memDC);
384       if(gdiBitmap.mask)
385          DeleteObject(gdiBitmap.mask);
386       if(gdiBitmap.bmp)
387          DeleteObject(gdiBitmap.bmp);
388       delete (Win32PrinterBitmap)gdiBitmap;
389       bitmap.driverData = null;
390       bitmap.driver = null;
391    }
392
393    bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
394    {
395       // return (((subclass(DisplayDriver))class(LFBDisplayDriver)).MakeDDBitmap(displaySystem, bitmap, mipMaps);
396
397       if(bitmap.Convert(null, pixelFormat888, null))
398       {
399          Win32PrinterSystem gdiSystem = displaySystem.driverData;
400          Win32PrinterBitmap gdiBitmap = bitmap.driverData = Win32PrinterBitmap { };
401          BITMAPINFO * info = new0 BITMAPINFO[1];
402          if(!info) return false;
403
404          info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
405          info->bmiHeader.biPlanes = 1;
406          info->bmiHeader.biWidth = bitmap.width;
407          info->bmiHeader.biHeight = -bitmap.height;
408          info->bmiHeader.biBitCount = 32;
409          // If transparent, we need to create a black mask for the little GDI trick
410          if(bitmap.transparent)
411          {
412             Bitmap mask { };
413             HGDIOBJ prevDC, prevDC2;
414             int c;
415             mask.Allocate(null, bitmap.width, bitmap.height, 0, pixelFormat888, false);
416             for(c = 0; c<bitmap.width * bitmap.height; c++)
417                ((Color *)mask.picture)[c] = ((ColorAlpha *)bitmap.picture)[c].a ? 0xFFFFFF : 0;
418
419             gdiBitmap.bmp = CreateDIBitmap(gdiSystem.hdc, (LPBITMAPINFOHEADER)info, CBM_INIT, mask.picture, info, DIB_RGB_COLORS);
420             gdiBitmap.mask = CreateBitmap(bitmap.width, bitmap.height, 1, 1, null);
421             prevDC = SelectObject(gdiSystem.bmpDC, gdiBitmap.bmp);
422             prevDC2 = SelectObject(gdiSystem.tmpDC, gdiBitmap.mask);
423             SetBkColor(gdiSystem.bmpDC, 0);
424             BitBlt(gdiSystem.tmpDC, 0, 0, bitmap.width, bitmap.height, gdiSystem.bmpDC, 0, 0, SRCCOPY);
425             SetBkColor(gdiSystem.bmpDC, 0);
426             SetTextColor(gdiSystem.bmpDC, 0xFFFFFF);
427
428             SelectObject(gdiSystem.bmpDC, prevDC);
429             DeleteObject(gdiBitmap.bmp);
430
431             gdiBitmap.bmp = CreateDIBitmap(gdiSystem.hdc, (LPBITMAPINFOHEADER)info, CBM_INIT, bitmap.picture, info, DIB_RGB_COLORS);
432             prevDC = SelectObject(gdiSystem.bmpDC, gdiBitmap.bmp);
433
434             /*
435             SetTextColor(gdiSystem.bmpDC, RGB(255,255,255));
436             SetBkColor(gdiSystem.bmpDC, RGB(0,0,0));
437             BitBlt(gdiSystem.bmpDC, 0, 0, bitmap.width, bitmap.height, gdiSystem.tmpDC, 0, 0, SRCAND);
438             SelectObject(gdiSystem.tmpDC, prevDC2);
439             SelectObject(gdiSystem.bmpDC, prevDC);            
440             SetTextColor(gdiSystem.bmpDC, RGB(0,0,0));
441             SetBkColor(gdiSystem.bmpDC, RGB(255,255,255));
442             SetBkColor(gdiSystem.tmpDC, RGB(255,255,255));
443             */
444             delete mask;
445          }
446          else
447          {
448             gdiBitmap.bmp = CreateDIBitmap(gdiSystem.hdc, (LPBITMAPINFOHEADER)info, CBM_INIT, bitmap.picture, info, DIB_RGB_COLORS);
449          }
450          
451          delete bitmap.picture;
452          delete info;
453
454          bitmap.driver = ((subclass(DisplayDriver))class(Win32PrinterDisplayDriver));
455          return true;
456       }
457       return false;
458    }
459
460    void ReleaseSurface(Display display, Surface surface)
461    {
462       Win32PrinterSurface gdiSurface = surface.driverData;
463       Win32PrinterDisplay gdiDisplay = display ? display.driverData : null;
464       if(gdiSurface)
465       {
466          if(gdiSurface.rgn)
467          {
468             SelectClipRgn(gdiSurface.hdc,null);
469             DeleteObject(gdiSurface.rgn);
470             gdiSurface.rgn = null;
471          }
472          // ((subclass(DisplayDriver))class(LFBDisplayDriver)).ReleaseSurface(display, surface);
473          delete gdiSurface;
474          surface.driverData = null;
475       }
476    }
477
478    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
479    {
480       return false;
481    }
482
483    bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
484    {
485       bool result = false;
486       Win32PrinterDisplay gdiDisplay = display.driverData;
487       if(gdiDisplay && !gdiDisplay.completed)
488       {
489          Win32PrinterSurface gdiSurface;
490          Win32PrinterSystem gdiSystem = display.displaySystem.driverData;
491
492          if((surface.driverData = gdiSurface = Win32PrinterSurface { }))
493          {
494             // if(((subclass(DisplayDriver))class(LFBDisplayDriver)).GetSurface(display, surface, x, y, clip))
495             {
496                gdiSurface.hdc = gdiDisplay.hdc ? gdiDisplay.hdc : gdiSystem.tmpDC;
497
498                gdiSurface.offset.x = x;
499                gdiSurface.offset.y = y;
500                gdiSurface.unclippedBox = gdiSurface.box = clip;
501
502                surface.width = gdiDisplay.width - x + 1;
503                surface.height = gdiDisplay.height - y + 1;
504                surface.offset.x = x * gdiDisplay.width / display.width;
505                surface.offset.y = y * gdiDisplay.height / display.height;
506                surface.unclippedBox = surface.box = 
507                {
508                   left = clip.left * gdiDisplay.width / display.width,
509                   top = clip.top * gdiDisplay.height / display.height,
510                   right = (clip.right+1) * gdiDisplay.width / display.width-1,
511                   bottom = (clip.bottom+1) * gdiDisplay.height / display.height-1
512                };
513          
514                gdiSurface.rgn = CreateRectRgn(
515                   surface.offset.x + surface.box.left,
516                   surface.offset.y + surface.box.top,
517                   surface.offset.x + surface.box.right + 1,
518                   surface.offset.y + surface.box.bottom + 1);
519
520                // x + clip.left, y+clip.top,x+clip.right+1,y+clip.bottom+1);
521
522                if(gdiSurface.rgn)
523                   SelectClipRgn(gdiSurface.hdc,gdiSurface.rgn);
524
525                SetDCBrushColor(gdiSurface.hdc, RGB(0,0,0));
526                SetDCPenColor(gdiSurface.hdc, RGB(255,255,255));
527
528                SetBkColor(gdiSystem.hdc, RGB(0,0,0));
529
530                result = true;
531             }
532          }
533       }
534       return result;
535    }
536
537    void Clip(Display display, Surface surface, Box clip)
538    {
539       Win32PrinterDisplay gdiDisplay = display.driverData;
540       Win32PrinterSurface gdiSurface = surface.driverData;
541       HRGN clippedRgn = null; 
542       if(clip != null)
543       {
544          Box box = clip;
545
546          box.Clip(gdiSurface.unclippedBox);
547
548          gdiSurface.box = box;
549          surface.box = 
550          {
551             left = box.left * gdiDisplay.width / display.width,
552             top = box.top * gdiDisplay.height / display.height,
553             right = (box.right+1) * gdiDisplay.width / display.width-1,
554             bottom = (box.bottom+1) * gdiDisplay.height / display.height-1
555          };
556
557          if(box.right > box.left && box.bottom > box.top)
558          {
559             box.left += gdiSurface.offset.x;
560             box.top  += gdiSurface.offset.y;
561             box.right+= gdiSurface.offset.x;
562             box.bottom += gdiSurface.offset.y;
563
564             gdiSurface.rgn = CreateRectRgn(
565                surface.offset.x + surface.box.left,
566                surface.offset.y + surface.box.top,
567                surface.offset.x + surface.box.right + 1,
568                surface.offset.y + surface.box.bottom + 1);
569
570             // clippedRgn = CreateRectRgn(box.left, box.top, box.right+1, box.bottom+1);
571          }
572          else
573             clippedRgn = CreateRectRgn(0, 0, 0, 0);
574          
575          if(clippedRgn)
576             SelectClipRgn(gdiSurface.hdc, clippedRgn);
577       }
578       else if(gdiSurface.clippedRgn)
579       {
580          surface.box = surface.unclippedBox;
581          gdiSurface.box = gdiSurface.unclippedBox;
582          SelectClipRgn(gdiSurface.hdc,gdiSurface.rgn);
583       }
584       if(gdiSurface.clippedRgn)
585          DeleteObject(gdiSurface.clippedRgn);
586       gdiSurface.clippedRgn = clippedRgn;
587    }
588
589    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
590    {
591       bool result = false;
592       Win32PrinterDisplay gdiDisplay = display.driverData;
593       // result = ((subclass(DisplayDriver))class(LFBDisplayDriver)).GrabScreen(display, bitmap, x,y, w,h);
594       return result;
595    }
596
597    void SetForeground(Display display, Surface surface, ColorAlpha color)
598    {
599       Win32PrinterSurface gdiSurface = surface.driverData;
600       Win32PrinterDisplay gdiDisplay = display ? display.driverData : null;
601       COLORREF rgb = RGB(color.color.r, color.color.g, color.color.b);
602       // ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetForeground(display, surface, color);
603       SetTextColor(gdiSurface.hdc, rgb);
604       gdiSurface.color = rgb;
605       SetDCPenColor(gdiSurface.hdc, rgb);
606    }
607
608    void SetBackground(Display display, Surface surface, ColorAlpha color)
609    {
610       Win32PrinterSurface gdiSurface = surface.driverData;
611       Win32PrinterDisplay gdiDisplay = display ? display.driverData : null;
612       COLORREF rgb;
613       /*
614       ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetBackground(display, surface, color);
615       if(gdiSurface.bitmap.pixelFormat == pixelFormat8 && display)
616          color = gdiSurface.bitmap.palette[gdiDisplay.rgbLookup[(uint16)(Color555) color]];
617       */
618       rgb = RGB(color.color.r, color.color.g, color.color.b);
619       gdiSurface.backColor = rgb;
620       SetBkColor(gdiSurface.hdc, rgb);
621       SetDCBrushColor(gdiSurface.hdc, rgb);
622    }
623
624    ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
625    {
626       return 0;
627    }
628
629    void PutPixel(Display display, Surface surface, int x, int y)
630    {
631       Win32PrinterDisplay gdiDisplay = display ? display.driverData : null;
632       Win32PrinterSurface gdiSurface = surface.driverData;
633
634       SetBkMode(gdiSurface.hdc, OPAQUE);
635       SetBkColor(gdiSurface.hdc, gdiSurface.color);
636       PatBlt(gdiSurface.hdc,
637          (int)((float)x * gdiDisplay.width / display.width) + surface.offset.x,
638          (int)((float)y * gdiDisplay.height / display.height) + surface.offset.y,
639          (int)((float)(x+1) * gdiDisplay.width / display.width)-1 + surface.offset.x+1, 
640          (int)((float)(y+1) * gdiDisplay.height / display.height)-1 + surface.offset.y+1,
641          PATCOPY);
642       SetBkColor(gdiSurface.hdc, gdiSurface.backColor);
643       SetBkMode(gdiSurface.hdc, surface.textOpacity ? OPAQUE : TRANSPARENT);
644    }
645
646    void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
647    {
648       Win32PrinterSurface gdiSurface = surface.driverData;
649       Win32PrinterDisplay gdiDisplay = display ? display.driverData : null;
650       int c = 0;
651
652       x1 = (int)((float)x1 * gdiDisplay.width / display.width) + surface.offset.x;
653       y1 = (int)((float)y1 * gdiDisplay.height / display.height) + surface.offset.y;
654       x2 = (int)((float)x2 * gdiDisplay.width / display.width) + surface.offset.x;
655       y2 = (int)((float)y2 * gdiDisplay.height / display.height) + surface.offset.y;
656       for(c = 0; c <= (float)gdiDisplay.width / display.width; c++)
657       {
658          if(x1 == x2)
659          {
660             MoveToEx(gdiSurface.hdc, x1, y1, null);
661             LineTo(gdiSurface.hdc, x2, y2 + (int)((float)gdiDisplay.width / display.width + 0.5)+1);
662             x1++;
663             x2++;
664          }
665          else if(y1 == y2)
666          {
667             MoveToEx(gdiSurface.hdc, x1, y1, null);
668             LineTo(gdiSurface.hdc, x2 + (int)((float)gdiDisplay.width / display.width + 0.5)+1, y2);
669             y1++;
670             y2++;
671          }
672          else
673          {
674             MoveToEx(gdiSurface.hdc, x1, y1, null);
675             LineTo(gdiSurface.hdc, x2 + (int)((float)gdiDisplay.width / display.width + 0.5)+1, y2 + (int)((float)gdiDisplay.width / display.width + 0.5)+1);
676             x1++;
677             x2++;
678          }
679       }
680    }
681
682    void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
683    {
684       Win32PrinterSurface gdiSurface = surface.driverData;
685       Win32PrinterDisplay gdiDisplay = display ? display.driverData : null;
686
687       int c;
688
689       SelectObject(gdiSurface.hdc,GetStockObject(NULL_BRUSH));
690       x1 = (int)((float)x1 * gdiDisplay.width / display.width) + surface.offset.x;
691       y1 = (int)((float)y1 * gdiDisplay.height / display.height) + surface.offset.y;
692       x2 = (int)((float)(x2) * gdiDisplay.width / display.width) + surface.offset.x;
693       y2 = (int)((float)(y2) * gdiDisplay.height / display.height) + surface.offset.y;
694       for(c = 0; c <= (float)gdiDisplay.width / display.width + 1.5; c++)
695       {
696          ::Rectangle(gdiSurface.hdc, x1, y1, x2, y2);
697          y1++; y2++;
698          x1++; x2++;
699       }
700       SelectObject(gdiSurface.hdc,GetStockObject(DC_BRUSH));
701    }
702
703    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
704    {
705       Win32PrinterDisplay gdiDisplay = display ? display.driverData : null;
706       Win32PrinterSurface gdiSurface = surface.driverData;
707      
708       x1 = (int)((float)x1 * gdiDisplay.width / display.width) + surface.offset.x;
709       y1 = (int)((float)y1 * gdiDisplay.height / display.height) + surface.offset.y;
710       x2 = (int)(((float)(x2+1) * gdiDisplay.width / display.width) + 0.5) + surface.offset.x;
711       y2 = (int)(((float)(y2+1) * gdiDisplay.height / display.height) + 0.5) + surface.offset.y;
712
713       SetBkMode(gdiSurface.hdc, OPAQUE);
714       SetBkColor(gdiSurface.hdc, gdiSurface.backColor);
715       SetDCBrushColor(gdiSurface.hdc, gdiSurface.backColor);
716       PatBlt(gdiSurface.hdc,x1,y1,x2-x1+1,y2-y1+1,PATCOPY);
717       SetBkMode(gdiSurface.hdc, surface.textOpacity ? OPAQUE : TRANSPARENT);
718    }
719
720    void Clear(Display display, Surface surface, ClearType type)
721    {
722       Win32PrinterSurface gdiSurface = surface.driverData;
723       if(type != depthBuffer)
724          Area(display, surface, gdiSurface.box.left, gdiSurface.box.top, gdiSurface.box.right, gdiSurface.box.bottom);
725    }
726
727    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
728    {
729       return true;
730    }
731
732    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
733    {
734       return false;
735    }
736
737    void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
738    {
739       Filter(display, surface, src, dx, dy, sx, sy, w, h, w, h);
740    }
741
742    void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
743    {
744       Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
745    }
746
747    void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
748    {
749       Win32PrinterDisplay gdiDisplay = display ? display.driverData : null;
750       Win32PrinterSystem gdiSystem = display.displaySystem.driverData;
751       Win32PrinterBitmap gdiBitmap = src.driverData;
752       Win32PrinterSurface gdiSurface = surface.driverData;
753
754       if(src.transparent)
755       {
756          SelectObject(gdiSystem.bmpDC, gdiBitmap.bmp);
757          SelectObject(gdiSystem.tmpDC, gdiBitmap.mask);
758
759          SetStretchBltMode(gdiSurface.hdc, HALFTONE); //COLORONCOLOR);
760          
761          SetBkColor(gdiSurface.hdc, 0xFFFFFF);
762          SetTextColor(gdiSurface.hdc, 0);
763          StretchBlt(gdiSurface.hdc, 
764             dx * gdiDisplay.width / display.width + surface.offset.x, 
765             dy * gdiDisplay.height / display.height + surface.offset.y,
766             (w) * gdiDisplay.width / display.width,
767             (h) * gdiDisplay.height / display.height,
768             gdiSystem.tmpDC, sx, sy,sw,sh, SRCAND);
769          StretchBlt(gdiSurface.hdc, 
770             dx * gdiDisplay.width / display.width + surface.offset.x, 
771             dy * gdiDisplay.height / display.height + surface.offset.y,
772             (w) * gdiDisplay.width / display.width,
773             (h) * gdiDisplay.height / display.height,
774             gdiSystem.bmpDC, sx, sy,sw,sh, SRCPAINT);
775          /*
776          StretchBlt(gdiSurface.hdc, 
777             dx * gdiDisplay.width / display.width + surface.offset.x, 
778             dy * gdiDisplay.height / display.height + surface.offset.y,
779             (w+1) * gdiDisplay.width / display.width-1,
780             (h+1) * gdiDisplay.height / display.height-1,
781             gdiSystem.tmpDC, sx, sy,sw,sh, SRCAND);
782          StretchBlt(gdiSurface.hdc, 
783             dx * gdiDisplay.width / display.width + surface.offset.x, 
784             dy * gdiDisplay.height / display.height + surface.offset.y,
785             (w+1) * gdiDisplay.width / display.width-1,
786             (h+1) * gdiDisplay.height / display.height-1,
787             gdiSystem.bmpDC, sx, sy,sw,sh, SRCPAINT);
788          */
789          SetBkColor(gdiSurface.hdc, gdiSurface.backColor);
790       }
791       else
792       {
793          SetStretchBltMode(gdiSurface.hdc, HALFTONE); //COLORONCOLOR);
794          SelectObject(gdiSystem.bmpDC, gdiBitmap.bmp);
795          StretchBlt(gdiSurface.hdc, 
796             dx * gdiDisplay.width / display.width + surface.offset.x, 
797             dy * gdiDisplay.height / display.height + surface.offset.y,
798             (w+1) * gdiDisplay.width / display.width-1,
799             (h+1) * gdiDisplay.height / display.height-1,
800             gdiSystem.bmpDC, sx, sy,sw,sh, SRCCOPY);
801       }
802    }
803
804    void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
805    {
806       Blit(display,surface,src,dx,dy,sx,sy,w,h);
807    }
808
809    void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
810    {
811       Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
812    }
813
814    void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
815    {
816       Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
817    }
818
819    Font LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags)
820    {
821       Win32PrinterSystem gdiSystem = displaySystem.driverData;
822       HDC hdc = gdiSystem.hdc;
823       int pixels, res;
824       void * font;
825       /*
826       SetMapMode(gdiSystem.hdc, MM_ANISOTROPIC);
827       SetWindowExtEx(gdiSystem.hdc, RESX, RESY, null);
828       SetViewportExtEx(gdiSystem.hdc, GetDeviceCaps(gdiSystem.hdc, HORZRES), GetDeviceCaps(gdiSystem.hdc, VERTRES), null);
829       */
830
831       pixels = GetDeviceCaps(hdc, VERTRES);
832       res = GetDeviceCaps(hdc, LOGPIXELSY);
833       {
834          int s;
835          s = -(int)(((float)size * res / 78) + 0.5);
836
837          // font = CreateFont(-(int)(((float)size * 96 / 72) + 0.5),
838          font = CreateFont(s,
839          // font = CreateFont(-(int)(((float)size * pixels * RESY / res / 72) + 0.5),
840             0,0,0, flags.bold ? FW_BOLD : FW_NORMAL, flags.italic ? TRUE : FALSE,
841                flags.underline ? TRUE : FALSE, 0, DEFAULT_CHARSET,
842                            OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
843                            DEFAULT_PITCH|FF_DONTCARE, faceName);
844       }
845       // SetMapMode(gdiSystem.hdc, MM_TEXT);
846       return font;
847    }
848
849    void UnloadFont(DisplaySystem displaySystem, Font font)
850    {
851       if(font)
852          DeleteObject(font);
853    }
854
855    void TextFont(Display display, Surface surface, Font font)
856    {
857       Win32PrinterSurface gdiSurface = surface.driverData;
858       SelectObject(gdiSurface.hdc, font);
859    }
860
861    void TextOpacity(Display display, Surface surface, bool opaque)
862    {
863       Win32PrinterSurface gdiSurface = surface.driverData;
864       SetBkMode(gdiSurface.hdc, opaque ? OPAQUE : TRANSPARENT);
865    }
866
867    void WriteText(Display display, Surface surface, int x, int y, char * text, int len)
868    {
869       Win32PrinterSurface gdiSurface = surface.driverData;
870       Win32PrinterDisplay gdiDisplay = display ? display.driverData : null;
871       int wordCount;
872       uint16 * u16text = UTF8toUTF16Len(text, len, &wordCount);
873
874       /*
875       SetMapMode(gdiSurface.hdc, MM_ANISOTROPIC);
876       SetWindowExtEx(gdiSurface.hdc, RESX, RESY, null);
877       SetViewportExtEx(gdiSurface.hdc, GetDeviceCaps(gdiSurface.hdc, HORZRES), GetDeviceCaps(gdiSurface.hdc, VERTRES), null);
878       */
879       TextOut(gdiSurface.hdc, x * gdiDisplay.width / display.width + surface.offset.x, y * gdiDisplay.height / display.height + surface.offset.y, u16text, wordCount);
880       /*
881       TextOut(gdiSurface.hdc, x + gdiSurface.offset.x, y + gdiSurface.offset.y, text,len);
882       SetMapMode(gdiSurface.hdc, MM_TEXT);
883       */
884       delete u16text;
885    }
886
887    void ::_TextExtent(HDC hdc, int resX, int resY, char * text, int len, int * width, int * height)
888    {
889       SIZE space, size;
890       uint realLen;
891       int wordCount;
892       uint16 * u16text = UTF8toUTF16Len(text, len, &wordCount);
893
894       for(realLen = 0; realLen<wordCount && u16text[realLen]; realLen++);
895       GetTextExtentPoint32(hdc, " ", 1, &space);
896       GetTextExtentPoint32(hdc, u16text, realLen, &size);
897       delete u16text;
898
899       if(width)
900       {
901           // UNICODE FIX: proper space computation
902           *width = size.cx + (wordCount - realLen) * space.cx;
903           *width = *width * resX / GetDeviceCaps(hdc, HORZRES);
904       }
905       if(height) 
906       {
907          if(realLen)
908             *height = size.cy;
909          else
910             *height = len ? space.cy : 0;
911          *height = *height * resY / GetDeviceCaps(hdc, VERTRES);
912       }
913    }
914    
915    void TextExtent(Display display, Surface surface, char * text, int len, int * width, int * height)
916    {
917       Win32PrinterDisplay gdiDisplay = display ? display.driverData : null;
918       Win32PrinterSystem gdiSystem = (display && display.displaySystem) ? display.displaySystem.driverData : null;
919       Win32PrinterSurface gdiSurface = surface.driverData;
920
921       _TextExtent(gdiSurface.hdc, gdiSystem.resX, gdiSystem.resY, text, len, width, height);
922    }
923
924    void FontExtent(DisplaySystem displaySystem, void * font, char * text, int len, int * width, int * height)
925    {
926       Win32PrinterSystem gdiSystem = displaySystem.driverData;
927       if(gdiSystem.hdc)
928       {
929          SelectObject(gdiSystem.hdc, font);
930          _TextExtent(gdiSystem.hdc, gdiSystem.resX, gdiSystem.resY, text, len, width, height);
931       }
932       else
933       {
934          if(width) *width = 0;
935          if(height) *height = 0;
936       }
937    }
938
939    void DrawingChar(Display display, Surface surface, byte character)
940    {
941
942    }
943
944    void LineStipple(Display display, Surface surface, uint stipple)
945    {
946       Win32PrinterDisplay gdiDisplay = display ? display.driverData : null;
947       // ((subclass(DisplayDriver))class(LFBDisplayDriver)).LineStipple(display, surface, stipple);
948    }
949
950    bool Lock(Display display)
951    {
952       return true;
953    }
954
955    void Unlock(Display display)
956    {
957    }
958 }
959
960 #endif