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