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