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