1 namespace gfx::drivers;
10 #define _WIN32_WINNT 0x0500
11 #define WIN32_LEAN_AND_MEAN
12 #define Method _Method
13 #define String _String
21 import "Win32Interface"
23 class GDIDisplay : LFBDisplay
28 LOGPALETTE * logPalette;
37 if(memDC) DeleteDC(memDC);
38 if(memBitmap) DeleteObject(memBitmap);
39 if(palette) DeleteObject(palette);
44 static byte defaultRGBLookup[32768];
45 static bool rgbLookupSet = false;
47 class GDISystem : LFBSystem
59 class GDISurface : LFBSurface
66 class GDIBitmap : struct
82 static PixelFormat GetColorFormat(int depth)
87 return pixelFormat555;
89 return pixelFormat888;
92 // TOFIX: Quick fix for GrabScreen called with a null Display
93 static DisplaySystem theDisplaySystem;
95 class GDIDisplayDriver : DisplayDriver
97 class_property(name) = "GDI";
99 bool CreateDisplaySystem(DisplaySystem displaySystem)
101 GDISystem gdiSystem = displaySystem.driverData = GDISystem { };
102 HDC hdc = GetDC(GetDesktopWindow());
105 gdiSystem.tmpDC = GetDC(0);
106 gdiSystem.depth = GetDeviceCaps(hdc, BITSPIXEL);
107 displaySystem.pixelFormat = GetColorFormat(gdiSystem.depth);
108 if(displaySystem.pixelFormat == pixelFormat8)
112 ColorAlpha realPalette[256];
113 gdiSystem.palette = new ColorAlpha[256];
114 GetSystemPaletteEntries(hdc,0,256,(PALETTEENTRY *)realPalette);
115 for(c = 0; c<256; c++)
116 gdiSystem.palette[c] = { 255, RGB(realPalette[c].color.r, realPalette[c].color.g, realPalette[c].color.b) };
117 CopyBytesBy4(gdiSystem.palette + reserved, GetDefaultPalette() + reserved, 256 - 2 * reserved);
120 for(c = 0; c<32768; c++)
121 defaultRGBLookup[c] = (byte)BestColorMatch(gdiSystem.palette, 0, 255, (Color555)c);
124 CopyBytes(gdiSystem.rgbLookup, defaultRGBLookup, 32768);
126 ReleaseDC(GetDesktopWindow(), hdc);
128 if(!theDisplaySystem) theDisplaySystem = displaySystem;
129 displaySystem.flags.memBackBuffer = true;
130 displaySystem.flags.scrolling = true;
131 displaySystem.flags.alpha = true;
135 void DestroyDisplaySystem(DisplaySystem displaySystem)
137 GDISystem gdiSystem = displaySystem.driverData;
138 delete gdiSystem.palette;
140 displaySystem.driverData = null;
141 if(theDisplaySystem == displaySystem) theDisplaySystem = null;
144 void DestroyDisplay(Display display)
146 GDIDisplay gdiDisplay = display.driverData;
147 ((subclass(DisplayDriver))class(LFBDisplayDriver)).DestroyDisplay(display);
149 display.driverData = null;
152 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
154 GDIDisplay gdiDisplay = display.driverData;
155 if(gdiDisplay.bitmap.pixelFormat == pixelFormat8)
158 ColorAlpha realPalette[256];
159 int reserved = (display.flags.fullScreen) ? 1 : 10;
160 HDC hdc = GetDC(display.window);
165 GetSystemPaletteEntries(hdc,0,256,(PALETTEENTRY *)realPalette);
166 for(c = 0; c<256; c++)
167 realPalette[c] = RGB(realPalette[c].color.r, realPalette[c].color.g, realPalette[c].color.b);
169 // *** Reserved Palette Handling ***
172 palette = GetDefaultPalette();
173 CopyBytesBy4(realPalette+reserved,palette+reserved,256-2*reserved);
174 CopyBytes(gdiDisplay.rgbLookup, defaultRGBLookup, 32768);
178 for(i=0; i<LIGHTSTEPS; i++)
180 gdiDisplay.lightTable[c][i] = gdiDisplay.rgbLookup[(uint16)Color555 {
181 (byte)(((uint16)realPalette[c].color.r*i) >> LIGHTSHIFT),
182 (byte)(((uint16)realPalette[c].color.g*i) >> LIGHTSHIFT),
183 (byte)(((uint16)realPalette[c].color.b*i) >> LIGHTSHIFT) }];
186 CopyBytesBy4(gdiDisplay.bitmap.palette, realPalette, 256);
190 CopyBytesBy4(realPalette+reserved,palette+reserved,256-2*reserved);
191 ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetPalette(display, realPalette, colorMatch);
195 ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetPalette(display, palette, colorMatch);
196 // *********************************
198 gdiDisplay.logPalette->palVersion = 0x300;
199 gdiDisplay.logPalette->palNumEntries = 256;
201 for(c = 0; c < 256; c++)
203 gdiDisplay.logPalette->palPalEntry[c].peFlags = PC_NOCOLLAPSE;
204 gdiDisplay.logPalette->palPalEntry[c].peRed = gdiDisplay.bitmap.palette[c].color.r;
205 gdiDisplay.logPalette->palPalEntry[c].peGreen = gdiDisplay.bitmap.palette[c].color.g;
206 gdiDisplay.logPalette->palPalEntry[c].peBlue = gdiDisplay.bitmap.palette[c].color.b;
209 if(!gdiDisplay.palette)
210 gdiDisplay.palette = CreatePalette(gdiDisplay.logPalette);
212 SetPaletteEntries(gdiDisplay.palette, 0, 256, gdiDisplay.logPalette->palPalEntry);
214 SelectPalette(hdc, gdiDisplay.palette, FALSE);
217 SetDIBColorTable(gdiDisplay.memDC, 0, 256, (RGBQUAD *)gdiDisplay.bitmap.palette);
219 ReleaseDC(display.window, hdc);
223 (((subclass(DisplayDriver))class(LFBDisplayDriver)).SetPalette(display, palette, colorMatch);*/
226 bool CreateDisplay(Display display)
232 GDIDisplay gdiDisplay = display.driverData = GDIDisplay { };
233 if((gdiDisplay.logPalette = (LOGPALETTE *)new0 byte[sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*256]) &&
234 ((subclass(DisplayDriver))class(LFBDisplayDriver)).CreateDisplay(display))
236 gdiDisplay.bitmap.pixelFormat = /*display.alphaBlend ? pixelFormat888 : */display.displaySystem.pixelFormat;
243 bool DisplaySize(Display display, int width, int height)
245 GDISystem gdiSystem = display.displaySystem.driverData;
246 GDIDisplay gdiDisplay = display.driverData;
248 HDC hdc = GetDC(display.window);
250 display.width = width;
251 display.height = height;
253 if(!width || !height)
259 if((info = (BITMAPINFO *)new0 byte[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256]))
264 if(gdiDisplay.memDC) DeleteDC(gdiDisplay.memDC);
265 gdiDisplay.memDC = CreateCompatibleDC(hdc);
266 SetMapMode(gdiDisplay.memDC, MM_TEXT);
268 gdiDisplay.bitmap.pixelFormat = /*display.alphaBlend ? pixelFormat888 : */display.displaySystem.pixelFormat;
270 switch(GetColorDepthShifts(gdiDisplay.bitmap.pixelFormat))
272 case 0: gdiDisplay.bitmap.stride = (width + 3) & 0xFFFFFFFC; break;
273 case 1: gdiDisplay.bitmap.stride = (width + 1) & 0xFFFFFFFE; break;
274 case 2: gdiDisplay.bitmap.stride = width; break;
276 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
277 info->bmiHeader.biPlanes = 1;
278 info->bmiHeader.biCompression = BI_RGB;
279 info->bmiHeader.biBitCount = (uint16)gdiSystem.depth;
280 info->bmiHeader.biWidth = gdiDisplay.bitmap.stride;
281 info->bmiHeader.biHeight = -height;
285 info->bmiColors[c].rgbReserved = 0;
286 info->bmiColors[c].rgbRed = gdiDisplay.bitmap.palette[c].color.r;
287 info->bmiColors[c].rgbGreen = gdiDisplay.bitmap.palette[c].color.g;
288 info->bmiColors[c].rgbBlue = gdiDisplay.bitmap.palette[c].color.b;
291 newBitmap = CreateDIBSection(hdc, info, DIB_RGB_COLORS, &gdiDisplay.bitmap.picture, null, 0);
294 SelectObject(gdiDisplay.memDC, newBitmap);
295 if(gdiDisplay.memBitmap) DeleteObject(gdiDisplay.memBitmap);
296 gdiDisplay.memBitmap = newBitmap;
298 //SelectObject(gdiDisplay.memDC,GetStockObject(DC_PEN));
299 //SelectObject(gdiDisplay.memDC,GetStockObject(DC_BRUSH));
301 result = ((subclass(DisplayDriver))class(LFBDisplayDriver)).DisplaySize(display, width, height);
304 Log("Error creating DIB Section\n");
307 ReleaseDC(display.window, hdc);
312 void DisplayPosition(Display display, int x, int y)
314 GDIDisplay gdiDisplay = display.driverData;
315 gdiDisplay.offset.x = x;
316 gdiDisplay.offset.y = y;
320 void RestorePalette(Display display)
322 GDIDisplay gdiDisplay = display.driverData;
323 HDC hdc = GetDC(display.window);
326 if(gdiDisplay.palette)
328 SelectPalette(hdc, gdiDisplay.palette, FALSE);
331 ReleaseDC(display.window,hdc);
335 #define MAX_EXPOSED 50
337 void StartUpdate(Display display)
339 GDIDisplay gdiDisplay = display.driverData;
340 if(!display.alphaBlend || display.pixelFormat != pixelFormat888)
342 GdiSetBatchLimit(1000);
343 gdiDisplay.hdc = GetDC(display.window);
345 gdiDisplay.rgn = CreateRectRgn(0,0,0,0);
346 //gdiDisplay.data = (RGNDATA *) new0 byte[(sizeof(RGNDATAHEADER) + sizeof(RECT) * MAX_EXPOSED)];
347 if(gdiDisplay.palette)
348 SelectPalette(gdiDisplay.hdc, gdiDisplay.palette, FALSE);
351 void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
353 GDIDisplay gdiDisplay = display.driverData;
361 if(!display.alphaBlend || display.pixelFormat != pixelFormat888)
363 // printf("Box: %d, %d, %d, %d\n", box.left, box.top, box.right, box.bottom);
364 ScrollDC(gdiDisplay.hdc, -x, -y, (RECT *)&box, (RECT *)&box, gdiDisplay.rgn, null);
366 ScrollDC(gdiDisplay.memDC, -x, -y, (RECT *)&box, (RECT *)&box, null, null);
368 numBytes = GetRegionData(gdiDisplay.rgn, 0, null);
369 gdiDisplay.data = (RGNDATA *) new0 byte[numBytes];
370 GetRegionData(gdiDisplay.rgn, numBytes, gdiDisplay.data);
372 // gdiDisplay.data = (RGNDATA *) new0 byte[(sizeof(RGNDATAHEADER) + sizeof(RECT) * MAX_EXPOSED)];
373 printf("Number of bytes needed: %d\n", numBytes);
374 gdiDisplay.data = (RGNDATA *) new0 byte[numBytes];
375 printf("Data: %X\n", gdiDisplay.data);
376 printf("Return Value: %d, Count: %d\n", numBytes, gdiDisplay.data->rdh.nCount);
379 int error = GetLastError();
380 printf("GetLastError Returned: %d\n", error);
384 for(i = 0; i<gdiDisplay.data->rdh.nCount; i++)
387 Box box = ((Box *)gdiDisplay.data->Buffer)[i];
391 dirty.UnionBox(box, temp);
394 delete gdiDisplay.data;
397 void Update(Display display, Box updateBox)
399 GDIDisplay gdiDisplay = display.driverData;
401 if(display.alphaBlend && display.pixelFormat == pixelFormat888)
404 POINT point = { gdiDisplay.offset.x, gdiDisplay.offset.y};
405 POINT srcPoint = { 0, 0 };
406 BLENDFUNCTION blend = { 0 };
408 size.cx = display.width;
409 size.cy = display.height;
410 blend.BlendOp = AC_SRC_OVER;
411 blend.BlendFlags = 0;
412 blend.SourceConstantAlpha = 255;
413 blend.AlphaFormat = AC_SRC_ALPHA;
414 UpdateLayeredWindow(display.window, hdc, &point, &size, gdiDisplay.memDC, &srcPoint, 0, &blend, ULW_ALPHA);
419 BitBlt(gdiDisplay.hdc,
420 updateBox.left,updateBox.top,
421 updateBox.right - updateBox.left + 1, updateBox.bottom - updateBox.top + 1,
422 gdiDisplay.memDC, updateBox.left, updateBox.top, SRCCOPY);
426 void EndUpdate(Display display)
428 GDIDisplay gdiDisplay = display.driverData;
429 DeleteObject(gdiDisplay.rgn);
430 if(!display.alphaBlend || display.pixelFormat != pixelFormat888)
431 ReleaseDC(display.window,gdiDisplay.hdc);
433 // delete gdiDisplay.data;
436 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
438 GDIBitmap gdiBitmap = bitmap.driverData;
443 DeleteDC(gdiBitmap.memDC);
444 gdiBitmap.memDC = null;
446 if(gdiBitmap.memBitmap)
448 DeleteObject(gdiBitmap.memBitmap);
449 gdiBitmap.memBitmap = null;
452 bitmap.driverData = null;
453 bitmap.picture = null;
454 if(bitmap.palette && bitmap.allocatePalette)
455 delete bitmap.palette;
457 bitmap.palette = null;
460 ((subclass(DisplayDriver))class(LFBDisplayDriver)).FreeBitmap(displaySystem, bitmap);
463 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
465 /*if(bitmap.alphaBlend)
468 return (((subclass(DisplayDriver))class(LFBDisplayDriver)).MakeDDBitmap(displaySystem, bitmap, mipMaps);
471 void ReleaseSurface(Display display, Surface surface)
473 GDISurface gdiSurface = surface.driverData;
474 GDIDisplay gdiDisplay = display ? display.driverData : null;
478 SelectClipRgn(gdiSurface.hdc,null);
479 DeleteObject(gdiSurface.rgn);
480 gdiSurface.rgn = null;
482 ((subclass(DisplayDriver))class(LFBDisplayDriver)).ReleaseSurface(display, surface);
483 // delete gdiSurface; THIS IS ALREDY DONE IN LFB
484 surface.driverData = null;
487 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
490 GDIBitmap gdiBitmap = bitmap.driverData;
491 GDISurface gdiSurface;
493 if((surface.driverData = gdiSurface = GDISurface { }))
495 if(((subclass(DisplayDriver))class(LFBDisplayDriver)).GetBitmapSurface(displaySystem, surface, bitmap, x, y, clip))
497 gdiSurface.hdc = gdiBitmap.memDC;
498 gdiSurface.rgn = CreateRectRgn(x+clip.left,y+clip.top,x+clip.right+1,y+clip.bottom+1);
502 SelectClipRgn(gdiSurface.hdc,gdiSurface.rgn);
503 surface.offset.x = x;
504 surface.offset.y = y;
505 surface.unclippedBox = surface.box = clip;
514 bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
517 GDIDisplay gdiDisplay = display.driverData;
518 GDISurface gdiSurface;
519 GDISystem gdiSystem = display.displaySystem.driverData;
521 if((surface.driverData = gdiSurface = GDISurface { }))
523 if(((subclass(DisplayDriver))class(LFBDisplayDriver)).GetSurface(display, surface, x, y, clip))
525 gdiSurface.hdc = gdiDisplay.memDC ? gdiDisplay.memDC : gdiSystem.tmpDC;
526 gdiSurface.rgn = CreateRectRgn(x+clip.left,y+clip.top,x+clip.right+1,y+clip.bottom+1);
530 SelectClipRgn(gdiSurface.hdc,gdiSurface.rgn);
531 surface.offset.x = x;
532 surface.offset.y = y;
533 surface.unclippedBox = surface.box = clip;
535 SetDCBrushColor(gdiSurface.hdc, RGB(0,0,0));
536 SetDCPenColor(gdiSurface.hdc, RGB(255,255,255));
545 void Clip(Display display, Surface surface, Box clip)
547 GDISurface gdiSurface = surface.driverData;
548 HRGN clippedRgn = null;
553 box.Clip(surface.unclippedBox);
557 if(box.right > box.left && box.bottom > box.top)
559 box.left += surface.offset.x;
560 box.top += surface.offset.y;
561 box.right+= surface.offset.x;
562 box.bottom += surface.offset.y;
563 clippedRgn = CreateRectRgn(box.left, box.top, box.right+1, box.bottom+1);
566 clippedRgn = CreateRectRgn(0, 0, 0, 0);
569 SelectClipRgn(gdiSurface.hdc,clippedRgn);
571 else if(gdiSurface.clippedRgn)
573 surface.box = surface.unclippedBox;
574 SelectClipRgn(gdiSurface.hdc,gdiSurface.rgn);
576 if(gdiSurface.clippedRgn)
577 DeleteObject(gdiSurface.clippedRgn);
578 gdiSurface.clippedRgn = clippedRgn;
581 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
586 GDIDisplay gdiDisplay = display.driverData;
587 result = ((subclass(DisplayDriver))class(LFBDisplayDriver)).GrabScreen(display, bitmap, x,y, w,h);
591 PixelFormat format = theDisplaySystem.pixelFormat;
592 if(bitmap.Allocate(null, w, h, 0, format, false))
594 BITMAPINFO *info = (BITMAPINFO *)new0 byte[sizeof(BITMAPINFO)+sizeof(RGBQUAD)*256];
595 HDC hdc = GetDC(HWND_DESKTOP);
596 HDC memDC = CreateCompatibleDC(hdc);
597 HBITMAP screenBmp = CreateCompatibleBitmap(hdc, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
598 HBITMAP back = SelectObject(memDC, screenBmp);
603 case pixelFormat8: depth = 8; break;
604 case pixelFormat555: depth = 16; break;
608 format = pixelFormat888;
610 BitBlt(memDC, 0,0, w,h, hdc,x,y,SRCCOPY);
612 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
613 info->bmiHeader.biPlanes = 1;
614 info->bmiHeader.biCompression = BI_RGB;
615 info->bmiHeader.biBitCount = depth;
616 info->bmiHeader.biWidth = bitmap.width;
617 info->bmiHeader.biHeight = -bitmap.height;
618 GetDIBits(memDC, screenBmp, 0, bitmap.height, bitmap.picture, info, DIB_RGB_COLORS);
619 // TODO: Proper indexed mode support
620 if(format == pixelFormat8)
621 bitmap.palette = GetDefaultPalette();
624 ReleaseDC(HWND_DESKTOP, hdc);
625 SelectObject(memDC, back);
626 DeleteObject(screenBmp);
635 void SetForeground(Display display, Surface surface, ColorAlpha color)
637 ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetForeground(display, surface, color);
638 if(true) //display.alphaBlend)
640 GDISurface gdiSurface = surface.driverData;
641 GDIDisplay gdiDisplay = display ? display.driverData : null;
642 COLORREF rgb = RGB(color.color.r, color.color.g, color.color.b);
644 SetTextColor(gdiSurface.hdc, rgb);
645 gdiSurface.color = rgb;
649 void SetBackground(Display display, Surface surface, ColorAlpha color)
651 ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetBackground(display, surface, color);
653 if(display && (!display.alphaBlend || display.pixelFormat != pixelFormat888))
655 GDISurface gdiSurface = surface.driverData;
656 GDIDisplay gdiDisplay = display ? display.driverData : null;
659 if(gdiSurface.bitmap.pixelFormat == pixelFormat8 && display)
660 color = gdiSurface.bitmap.palette[gdiDisplay.rgbLookup[(uint16)(Color555) color]];
661 rgb = RGB(color.color.r, color.color.g, color.color.b);
663 SetBkColor(gdiSurface.hdc, rgb);
664 SetDCBrushColor(gdiSurface.hdc, rgb);
665 SetDCPenColor(gdiSurface.hdc, rgb);
669 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
674 void PutPixel(Display display, Surface surface, int x, int y)
676 GDIDisplay gdiDisplay = display ? display.driverData : null;
677 //GDISurface gdiSurface = surface.driverData;
678 // SetPixel(gdiSurface.hdc, x + surface.offset.x, y + surface.offset.y, gdiSurface.color);
679 ((subclass(DisplayDriver))class(LFBDisplayDriver)).PutPixel(display, surface, x,y);
682 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
684 GDIDisplay gdiDisplay = display ? display.driverData : null;
685 ((subclass(DisplayDriver))class(LFBDisplayDriver)).DrawLine(display, surface, x1,y1,x2,y2);
688 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
690 GDIDisplay gdiDisplay = display ? display.driverData : null;
691 ((subclass(DisplayDriver))class(LFBDisplayDriver)).Rectangle(display, surface, x1,y1,x2,y2);
694 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
696 GDIDisplay gdiDisplay = display ? display.driverData : null;
697 ((subclass(DisplayDriver))class(LFBDisplayDriver)).Area(display, surface, x1,y1,x2,y2);
700 GDISurface gdiSurface = surface.driverData;
701 x1 += surface.offset.x;
702 x2 += surface.offset.x;
703 y1 += surface.offset.y;
704 y2 += surface.offset.y;
705 SetBkMode(gdiSurface.hdc, OPAQUE);
706 //SetDCBrushColor(gdiSurface.hdc, BGR(eSystem_GetRandom(0,255), eSystem_GetRandom(0,255), eSystem_GetRandom(0,255)));
707 PatBlt(gdiSurface.hdc,x1,y1,x2-x1+1,y2-y1+1,PATCOPY);
708 SetBkMode(gdiSurface.hdc, surface.textOpacity ? OPAQUE : TRANSPARENT);
712 void Clear(Display display, Surface surface, ClearType type)
714 /*if(type != depthBuffer)
715 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);*/
716 ((subclass(DisplayDriver))class(LFBDisplayDriver)).Clear(display, surface, type);
719 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
725 return ((subclass(DisplayDriver))class(LFBDisplayDriver)).ConvertBitmap(displaySystem, src, format, palette);
729 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
732 HWND hwnd = displaySystem ? displaySystem.window : GetDesktopWindow();
733 HDC hdc = GetDC(hwnd);
736 GDIBitmap gdiBitmap = bitmap.driverData = GDIBitmap { };
739 BITMAPINFO *info = (BITMAPINFO *)new0 byte[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256];
748 case pixelFormat8: depth = 8; break;
749 case pixelFormat555: depth = 16; break;
753 format = pixelFormat888;
758 switch(GetColorDepthShifts(format))
760 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
761 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
762 case 2: stride = width; break;
766 bitmap.stride=stride;
768 bitmap.height=height;
769 bitmap.size=(uint)stride*(uint)height;
770 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
771 bitmap.pixelFormat = format;
772 bitmap.transparent = false;
773 bitmap.allocatePalette = allocatePalette;
776 bitmap.palette = new0 ColorAlpha[256];
778 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
781 bitmap.palette = GetDefaultPalette();
783 gdiBitmap.memDC = CreateCompatibleDC(hdc);
785 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
786 info->bmiHeader.biPlanes = 1;
787 info->bmiHeader.biCompression = BI_RGB;
788 info->bmiHeader.biBitCount = depth;
789 info->bmiHeader.biWidth = bitmap.stride;
790 info->bmiHeader.biHeight = -height;
794 info->bmiColors[c].rgbReserved = 0;
795 info->bmiColors[c].rgbRed = bitmap.palette[c].color.r;
796 info->bmiColors[c].rgbGreen = bitmap.palette[c].color.g;
797 info->bmiColors[c].rgbBlue = bitmap.palette[c].color.b;
800 gdiBitmap.memBitmap = CreateDIBSection(hdc, info, DIB_RGB_COLORS, &bitmap.picture, null, 0);
801 if(gdiBitmap.memBitmap)
803 SelectObject(gdiBitmap.memDC, gdiBitmap.memBitmap);
804 SetBkMode(gdiBitmap.memDC, TRANSPARENT);
810 FreeBitmap(displaySystem, bitmap);
813 ReleaseDC(hwnd, hdc);
818 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
820 GDIDisplay gdiDisplay = display ? display.driverData : null;
821 ((subclass(DisplayDriver))class(LFBDisplayDriver)).Blit(display, surface, src, dx, dy, sx, sy, w, h);
824 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
826 GDIDisplay gdiDisplay = display ? display.driverData : null;
827 ((subclass(DisplayDriver))class(LFBDisplayDriver)).Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
830 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
832 GDIDisplay gdiDisplay = display ? display.driverData : null;
833 ((subclass(DisplayDriver))class(LFBDisplayDriver)).Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
836 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
838 Blit(display,surface,src,dx,dy,sx,sy,w,h);
841 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
843 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
846 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
848 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
851 Font LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags)
853 if(false) //display.alphaBlend)
854 return ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
858 HDC hdc = GetDC(null);
859 int pixels = GetDeviceCaps(hdc, LOGPIXELSY);
860 strcpy(font.faceName, faceName);
863 font.gdiFont = CreateFontA(-(int)((float)size * pixels / 72 + 0.5),
864 0,0,0, flags.bold ? FW_BOLD : FW_NORMAL, flags.italic ? TRUE : FALSE,
865 flags.underline ? TRUE : FALSE, 0, DEFAULT_CHARSET,
866 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
867 DEFAULT_PITCH|FF_DONTCARE, faceName);
869 ReleaseDC(null, hdc);
874 void UnloadFont(DisplaySystem displaySystem, Font font)
876 GDIFont gdiFont = (GDIFont) font;
877 if(false) //display.alphaBlend)
878 ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
882 DeleteObject(gdiFont.gdiFont);
884 ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, gdiFont.font);
889 void TextFont(Display display, Surface surface, Font font)
891 GDIFont gdiFont = (GDIFont) font;
892 if(display.alphaBlend && display.pixelFormat == pixelFormat888)
896 gdiFont.font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(display.displaySystem,
897 gdiFont.faceName, gdiFont.size, gdiFont.flags);
899 ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, gdiFont.font);
903 GDISurface gdiSurface = surface.driverData;
904 SelectObject(gdiSurface.hdc, gdiFont.gdiFont);
908 void TextOpacity(Display display, Surface surface, bool opaque)
910 ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextOpacity(display, surface, opaque);
911 if(display && (!display.alphaBlend || display.pixelFormat != pixelFormat888))
913 GDISurface gdiSurface = surface.driverData;
914 SetBkMode(gdiSurface.hdc, opaque ? OPAQUE : TRANSPARENT);
918 void WriteText(Display display, Surface surface, int x, int y, char * text, int len)
920 if(display.alphaBlend && display.pixelFormat == pixelFormat888)
922 GDIFont gdiFont = (GDIFont)surface.font;
925 gdiFont.font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(display.displaySystem,
926 gdiFont.faceName, gdiFont.size, gdiFont.flags);
928 if(surface.textOpacity)
931 ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(display.displaySystem, gdiFont.font, text, len, &w, &h);
932 Area(display, surface, x, y, x+w-1, y+h-1);
934 ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len);
938 GDISurface gdiSurface = surface.driverData;
940 uint16 * u16text = UTF8toUTF16Len(text, len, &wordCount);
942 TextOut(gdiSurface.hdc, x + surface.offset.x, y + surface.offset.y, u16text, wordCount);
943 if(display.alphaBlend && display.pixelFormat == pixelFormat888)
946 FontExtent(display.displaySystem, surface.font, text, len, &w, &h);
947 surface.writeColor = false;
948 SetBackground(display, surface, surface.foreground);
949 Area(display, surface,x-2,y-2,x+w+1,y+h+1);
950 SetBackground(display, surface, surface.background);
951 surface.writeColor = true;
957 void TextExtent(Display display, Surface surface, char * text, int len, int * width, int * height)
959 if(display && display.alphaBlend && display.pixelFormat == pixelFormat888)
960 ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextExtent(display, surface, text, len, width, height);
963 GDISurface gdiSurface = surface.driverData;
967 uint16 * u16text = UTF8toUTF16Len(text, len, &wordCount);
969 for(realLen = 0; realLen<wordCount && u16text[realLen]; realLen++);
970 GetTextExtentPoint32A(gdiSurface.hdc, " ", 1, &space);
971 GetTextExtentPoint32(gdiSurface.hdc, u16text, realLen, &size);
974 // UNICODE FIX: proper space computation
975 if(width) *width = size.cx + (wordCount - realLen) * space.cx;
981 *height = wordCount ? space.cy : 0;
986 void FontExtent(DisplaySystem displaySystem, Font font, char * text, int len, int * width, int * height)
988 if(false) //display.alphaBlend)
989 ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height);
992 GDISystem gdiSystem = displaySystem.driverData;
996 GDIFont gdiFont = (GDIFont)font;
997 GDISurface gdiSurface { };
999 surface.driverData = gdiSurface;
1000 gdiSurface.hdc = gdiSystem.tmpDC;
1002 SelectObject(gdiSurface.hdc, gdiFont ? gdiFont.gdiFont : null);
1003 TextExtent(null, surface, text, len, width, height);
1010 if(width) *width = 0;
1011 if(height) *height = 0;
1016 void DrawingChar(Display display, Surface surface, byte character)
1021 void LineStipple(Display display, Surface surface, uint stipple)
1023 GDIDisplay gdiDisplay = display ? display.driverData : null;
1024 ((subclass(DisplayDriver))class(LFBDisplayDriver)).LineStipple(display, surface, stipple);
1027 bool Lock(Display display)
1032 void Unlock(Display display)