4 * Copyright 2009 Massimo Del Fedele
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv
);
29 static const DASHPATTERN dashPatterns
[4] =
34 {6, {9, 3, 3, 3, 3, 3}}
37 static inline void OrderEndPoints(int *s
, int *e
)
48 static void SolidPenHLine(DIBDRVPHYSDEV
*physDev
, int x1
, int x2
, int y
)
50 OrderEndPoints(&x1
, &x2
);
51 physDev
->physBitmap
->funcs
->SolidHLine(physDev
->physBitmap
, x1
, x2
, y
, physDev
->penAnd
, physDev
->penXor
);
54 static void SolidPenVLine(DIBDRVPHYSDEV
*physDev
, int x
, int y1
, int y2
)
56 OrderEndPoints(&y1
, &y2
);
57 physDev
->physBitmap
->funcs
->SolidVLine(physDev
->physBitmap
, x
, y1
, y2
, physDev
->penAnd
, physDev
->penXor
);
60 static void WINAPI
SolidPenLineCallback(int x
, int y
, LPARAM lparam
)
62 DIBDRVPHYSDEV
*physDev
= (DIBDRVPHYSDEV
*)lparam
;
64 physDev
->physBitmap
->funcs
->SetPixel(physDev
->physBitmap
, x
, y
, physDev
->penAnd
, physDev
->penXor
);
68 static void SolidPenLine(DIBDRVPHYSDEV
*physDev
, int x1
, int y1
, int x2
, int y2
)
70 LineDDA(x1
, y1
, x2
, y2
, SolidPenLineCallback
, (LPARAM
)physDev
);
73 static inline void GetDashColors(DIBDRVPHYSDEV
*physDev
, DWORD
*and, DWORD
*xor)
75 if(physDev
->markSpace
== mark
)
77 *and = physDev
->penAnd
;
78 *xor = physDev
->penXor
;
80 else if(GetBkMode(physDev
->hdc
) == OPAQUE
)
82 *and = physDev
->backgroundAnd
;
83 *xor = physDev
->backgroundXor
;
92 static inline void NextDash(DIBDRVPHYSDEV
*physDev
)
94 if(physDev
->leftInDash
!= 0)
98 if(physDev
->curDash
== physDev
->penPattern
->count
)
100 physDev
->leftInDash
= physDev
->penPattern
->dashes
[physDev
->curDash
];
101 if(physDev
->markSpace
== mark
)
102 physDev
->markSpace
= space
;
104 physDev
->markSpace
= mark
;
107 static void DashedPenHLine(DIBDRVPHYSDEV
*physDev
, int x1
, int x2
, int y
)
117 GetDashColors(physDev
, &and, &xor);
119 dashLen
= physDev
->leftInDash
;
123 physDev
->physBitmap
->funcs
->SolidHLine(physDev
->physBitmap
, x
, x
+ dashLen
, y
, and, xor);
126 physDev
->leftInDash
-= dashLen
;
134 GetDashColors(physDev
, &and, &xor);
136 dashLen
= physDev
->leftInDash
;
137 if(x
- (int)dashLen
< x2
)
140 physDev
->physBitmap
->funcs
->SolidHLine(physDev
->physBitmap
, x
- dashLen
+ 1, x
+ 1, y
, and, xor);
143 physDev
->leftInDash
-= dashLen
;
149 static void DashedPenVLine(DIBDRVPHYSDEV
*physDev
, int x
, int y1
, int y2
)
159 GetDashColors(physDev
, &and, &xor);
161 dashLen
= physDev
->leftInDash
;
165 physDev
->physBitmap
->funcs
->SolidVLine(physDev
->physBitmap
, x
, y
, y
+ dashLen
, and, xor);
168 physDev
->leftInDash
-= dashLen
;
176 GetDashColors(physDev
, &and, &xor);
178 dashLen
= physDev
->leftInDash
;
179 if(y
- (int)dashLen
< y2
)
182 physDev
->physBitmap
->funcs
->SolidVLine(physDev
->physBitmap
, x
, y
- dashLen
+ 1, y
+ 1, and, xor);
185 physDev
->leftInDash
-= dashLen
;
191 static void WINAPI
DashedPenLineCallback(int x
, int y
, LPARAM lparam
)
193 DIBDRVPHYSDEV
*physDev
= (DIBDRVPHYSDEV
*)lparam
;
196 GetDashColors(physDev
, &and, &xor);
198 physDev
->physBitmap
->funcs
->SetPixel(physDev
->physBitmap
, x
, y
, and, xor);
200 physDev
->leftInDash
--;
206 static void DashedPenLine(DIBDRVPHYSDEV
*physDev
, int x1
, int y1
, int x2
, int y2
)
208 LineDDA(x1
, y1
, x2
, y2
, DashedPenLineCallback
, (LPARAM
)physDev
);
211 void _DIBDRV_ResetDashOrigin(DIBDRVPHYSDEV
*physDev
)
213 physDev
->curDash
= 0;
214 if(physDev
->penPattern
)
215 physDev
->leftInDash
= physDev
->penPattern
->dashes
[0];
216 physDev
->markSpace
= mark
;
220 /* For 1bpp bitmaps, unless the selected foreground color exactly
221 matches foreground's colortable OR it's the WHITE color,
222 the background color is used -- tested on WinXP */
223 static DWORD
AdjustFgColor(DIBDRVPHYSDEV
*physDev
, COLORREF color
)
225 RGBQUAD
*back
= physDev
->physBitmap
->colorTable
;
226 RGBQUAD
*fore
= physDev
->physBitmap
->colorTable
+1;
229 fore
->rgbRed
== GetRValue(color
) &&
230 fore
->rgbGreen
== GetGValue(color
) &&
231 fore
->rgbBlue
== GetBValue(color
))
234 back
->rgbRed
== GetRValue(color
) &&
235 back
->rgbGreen
== GetGValue(color
) &&
236 back
->rgbBlue
== GetBValue(color
))
238 else if((color
& 0x00ffffff) == 0x00ffffff)
244 static void FixupFgColors1(DIBDRVPHYSDEV
*physDev
)
246 int rop
= GetROP2(physDev
->hdc
);
248 physDev
->penColor
= AdjustFgColor(physDev
, physDev
->penColorref
);
249 physDev
->brushColor
= AdjustFgColor(physDev
, physDev
->brushColorref
);
251 _DIBDRV_CalcAndXorMasks(rop
, physDev
->penColor
, &physDev
->penAnd
, &physDev
->penXor
);
252 _DIBDRV_CalcAndXorMasks(rop
, physDev
->brushColor
, &physDev
->brushAnd
, &physDev
->brushXor
);
253 HeapFree(GetProcessHeap(), 0, physDev
->brushAnds
);
254 HeapFree(GetProcessHeap(), 0, physDev
->brushXors
);
255 physDev
->brushAnds
= NULL
;
256 physDev
->brushXors
= NULL
;
261 /* For 1bpp bitmaps, unless the selected foreground color exactly
262 matches one of the colors in the colortable, then the color that
263 isn't the bkgnd color is used. */
264 static DWORD
AdjustFgColor(DIBDRVPHYSDEV
*physDev
, COLORREF color
)
269 rgb
.rgbRed
= GetRValue(color
);
270 rgb
.rgbGreen
= GetGValue(color
);
271 rgb
.rgbBlue
= GetBValue(color
);
273 for(i
= 0; i
< physDev
->physBitmap
->colorTableSize
; i
++)
275 RGBQUAD
*cur
= physDev
->physBitmap
->colorTable
+ i
;
276 if((rgb
.rgbRed
== cur
->rgbRed
) && (rgb
.rgbGreen
== cur
->rgbGreen
) && (rgb
.rgbBlue
== cur
->rgbBlue
))
279 return ~physDev
->backgroundColor
& 1;
282 static void FixupFgColors1(DIBDRVPHYSDEV
*physDev
)
284 int rop
= GetROP2(physDev
->hdc
);
286 physDev
->penColor
= AdjustFgColor(physDev
, physDev
->penColorref
);
287 physDev
->brushColor
= AdjustFgColor(physDev
, physDev
->brushColorref
);
289 _DIBDRV_CalcAndXorMasks(rop
, physDev
->penColor
, &physDev
->penAnd
, &physDev
->penXor
);
290 _DIBDRV_CalcAndXorMasks(rop
, physDev
->brushColor
, &physDev
->brushAnd
, &physDev
->brushXor
);
291 HeapFree(GetProcessHeap(), 0, physDev
->brushAnds
);
292 HeapFree(GetProcessHeap(), 0, physDev
->brushXors
);
293 physDev
->brushAnds
= NULL
;
294 physDev
->brushXors
= NULL
;
298 static void SolidBrushHLine(DIBDRVPHYSDEV
*physDev
, int x1
, int x2
, int y
)
300 OrderEndPoints(&x1
, &x2
);
301 physDev
->physBitmap
->funcs
->SolidHLine(physDev
->physBitmap
, x1
, x2
, y
, physDev
->brushAnd
, physDev
->brushXor
);
305 static void GenerateMasks(DIBDRVPHYSDEV
*physDev
, DIBDRVBITMAP
*bmp
, DWORD
**and, DWORD
**xor)
307 int rop
= GetROP2(physDev
->hdc
);
308 DWORD
*color_ptr
, *and_ptr
, *xor_ptr
;
309 DWORD size
= bmp
->height
* abs(bmp
->stride
);
311 *and = HeapAlloc(GetProcessHeap(), 0, size
);
312 *xor = HeapAlloc(GetProcessHeap(), 0, size
);
314 color_ptr
= bmp
->bits
;
320 _DIBDRV_CalcAndXorMasks(rop
, *color_ptr
++, and_ptr
++, xor_ptr
++);
325 static void PatternBrushHLine(DIBDRVPHYSDEV
*physDev
, int x1
, int x2
, int y
)
327 DWORD
*and, *xor, brushY
= y
% physDev
->brushBitmap
->height
;
329 if(!physDev
->brushAnds
)
330 GenerateMasks(physDev
, physDev
->brushBitmap
, &physDev
->brushAnds
, &physDev
->brushXors
);
332 OrderEndPoints(&x1
, &x2
);
333 and = (DWORD
*)((char *)physDev
->brushAnds
+ brushY
* physDev
->brushBitmap
->stride
);
334 xor = (DWORD
*)((char *)physDev
->brushXors
+ brushY
* physDev
->brushBitmap
->stride
);
336 physDev
->physBitmap
->funcs
->PatternHLine(physDev
->physBitmap
, x1
, x2
, y
, and, xor, physDev
->brushBitmap
->width
, x1
% physDev
->brushBitmap
->width
);
339 /* null function for PS_NULL and BS_NULL pen and brush styles */
340 void NullPenHLine(DIBDRVPHYSDEV
*physDev
, int x1
, int x2
, int y
) {}
341 void NullPenVLine(DIBDRVPHYSDEV
*physDev
, int x
, int y1
, int y2
) {}
342 void NullPenLine(DIBDRVPHYSDEV
*physDev
, int x1
, int y1
, int x2
, int y2
) {}
343 void NullBrushHLine(DIBDRVPHYSDEV
*physDev
, int x1
, int x2
, int y
) {}
345 /***********************************************************************
348 HPEN
DIBDRV_SelectPen( DIBDRVPHYSDEV
*physDev
, HPEN hpen
)
353 MAYBE(TRACE("physDev:%p, hpen:%p\n", physDev
, hpen
));
357 GetObjectW(hpen
, sizeof(logpen
), &logpen
);
359 physDev
->penColorref
= logpen
.lopnColor
;
360 physDev
->penColor
= physDev
->physBitmap
->funcs
->ColorToPixel(
362 _DIBDRV_MapColor(physDev
, physDev
->penColorref
));
364 _DIBDRV_CalcAndXorMasks(GetROP2(physDev
->hdc
), physDev
->penColor
, &physDev
->penAnd
, &physDev
->penXor
);
366 physDev
->penStyle
= logpen
.lopnStyle
;
367 switch(logpen
.lopnStyle
)
370 ONCE(FIXME("Unhandled pen style %d\n", logpen
.lopnStyle
));
371 physDev
->penStyle
= PS_SOLID
;
374 physDev
->penHLine
= SolidPenHLine
;
375 physDev
->penVLine
= SolidPenVLine
;
376 physDev
->penLine
= SolidPenLine
;
377 physDev
->penPattern
= NULL
;
384 physDev
->penHLine
= DashedPenHLine
;
385 physDev
->penVLine
= DashedPenVLine
;
386 physDev
->penLine
= DashedPenLine
;
387 physDev
->penPattern
= &dashPatterns
[logpen
.lopnStyle
- PS_DASH
];
388 _DIBDRV_ResetDashOrigin(physDev
);
391 physDev
->penHLine
= NullPenHLine
;
392 physDev
->penVLine
= NullPenVLine
;
393 physDev
->penLine
= NullPenLine
;
394 physDev
->penPattern
= NULL
;
401 /* DDB selected in, use X11 driver */
402 res
= _DIBDRV_GetDisplayDriver()->pSelectPen(physDev
->X11PhysDev
, hpen
);
407 /***********************************************************************
408 * DIBDRV_SetDCPenColor
410 COLORREF
DIBDRV_SetDCPenColor( DIBDRVPHYSDEV
*physDev
, COLORREF crColor
)
414 MAYBE(TRACE("physDev:%p, crColor:%x\n", physDev
, crColor
));
418 /* DIB section selected in, use DIB Engine */
419 ONCE(FIXME("STUB\n"));
424 /* DDB selected in, use X11 driver */
425 res
= _DIBDRV_GetDisplayDriver()->pSetDCPenColor(physDev
->X11PhysDev
, crColor
);
430 /***********************************************************************
433 HBRUSH
DIBDRV_SelectBrush( DIBDRVPHYSDEV
*physDev
, HBRUSH hbrush
)
439 MAYBE(TRACE("physDev:%p, hbrush:%p\n", physDev
, hbrush
));
443 GetObjectW(hbrush
, sizeof(logbrush
), &logbrush
);
445 /* frees any currently selected DIB brush and cache */
446 _DIBDRVBITMAP_Free(physDev
->brushBitmap
);
447 physDev
->brushBitmap
= NULL
;
448 _DIBDRVBITMAP_Free(physDev
->brushBmpCache
);
449 physDev
->brushBmpCache
= NULL
;
450 if(physDev
->brushAnds
)
452 HeapFree(GetProcessHeap(), 0, physDev
->brushAnds
);
453 HeapFree(GetProcessHeap(), 0, physDev
->brushXors
);
455 physDev
->brushAnds
= NULL
;
456 physDev
->brushXors
= NULL
;
458 switch (logbrush
.lbStyle
)
461 FIXME("Unhandled brush style %d\n", logbrush
.lbStyle
);
462 physDev
->brushColorref
= 0;
466 physDev
->brushColorref
= logbrush
.lbColor
;
468 MAYBE(TRACE("SOLID Pattern -- color is %x\n", physDev
->brushColorref
));
469 physDev
->brushStyle
= BS_SOLID
;
470 physDev
->brushHLine
= SolidBrushHLine
;
472 physDev
->brushColor
= physDev
->physBitmap
->funcs
->ColorToPixel(
474 _DIBDRV_MapColor(physDev
, physDev
->brushColorref
));
476 _DIBDRV_CalcAndXorMasks(physDev
->rop2
, physDev
->brushColor
,
477 &physDev
->brushAnd
, &physDev
->brushXor
);
479 /* set the physDev brush style */
480 physDev
->brushStyle
= BS_SOLID
;
481 physDev
->isBrushBitmap
= FALSE
;
485 case BS_DIBPATTERN8X8
:
491 FIXME("DIB Pattern\n");
493 /* if no DIB selected in, fallback to null brush */
494 if(!physDev
->physBitmap
->bits
)
496 physDev
->brushColorref
= 0;
500 /* gets brush DIB's pointer */
501 bmi
= GlobalLock((HGLOBAL
)logbrush
.lbHatch
);
503 /* initializes a temporary DIB with brush's one */
504 if(!_DIBDRVBITMAP_InitFromBitmapinfo(&src
, bmi
, NULL
))
506 ERR("Failed to initialize brush DIB\n");
511 /* converts brush bitmap to match currently selected one's format */
512 if(!_DIBDRVBITMAP_Convert(physDev
->brushBitmap
, &src
, physDev
->physBitmap
))
514 ERR("Failed to convert brush DIB\n");
515 _DIBDRVBITMAP_Free(&src
);
520 /* frees temporary DIB's data */
521 _DIBDRVBITMAP_Free(&src
);
523 /* use DIB pattern for brush lines */
524 physDev
->brushHLine
= PatternBrushHLine
;
527 /* frees brush's DIB pointer */
528 GlobalUnlock((HGLOBAL
)logbrush
.lbHatch
);
532 case BS_DIBPATTERNPT
:
533 FIXME("BS_DIBPATTERNPT not supported\n");
534 physDev
->brushColorref
= 0;
538 FIXME("BS_HATCHED not supported\n");
539 physDev
->brushColorref
= 0;
544 MAYBE(TRACE("NULL Pattern\n"));
545 physDev
->brushColorref
= 0;
546 physDev
->brushColor
= physDev
->physBitmap
->funcs
->ColorToPixel(
548 _DIBDRV_MapColor(physDev
, 0));
549 physDev
->brushHLine
= NullBrushHLine
;
555 FIXME("BS_PATTERN not supported\n");
556 physDev
->brushColorref
= 0;
560 MAYBE(TRACE("END\n"));
565 /* DDB selected in, use X11 driver */
567 /* we must check if a DIB pattern is requested */
568 GetObjectW(hbrush
, sizeof(logbrush
), &logbrush
);
569 switch (logbrush
.lbStyle
)
571 case BS_DIBPATTERN8X8
:
573 case BS_DIBPATTERNPT
:
574 FIXME("A DIB pattern was requested for a DDB bitmap\n");
585 res
= _DIBDRV_GetDisplayDriver()->pSelectBrush(physDev
->X11PhysDev
, hbrush
);
590 /***********************************************************************
591 * DIBDRV_SetDCBrushColor
593 COLORREF
DIBDRV_SetDCBrushColor( DIBDRVPHYSDEV
*physDev
, COLORREF crColor
)
597 MAYBE(TRACE("physDev:%p, crColor:%x\n", physDev
, crColor
));
601 /* DIB section selected in, use DIB Engine */
602 ONCE(FIXME("STUB\n"));
607 /* DDB selected in, use X11 driver */
608 res
= _DIBDRV_GetDisplayDriver()->pSetDCBrushColor(physDev
->X11PhysDev
, crColor
);
613 /***********************************************************************
616 int DIBDRV_SetROP2( DIBDRVPHYSDEV
*physDev
, int rop
)
620 MAYBE(TRACE("physDev:%p, rop:%x\n", physDev
, rop
));
622 prevRop
= physDev
->rop2
;
627 _DIBDRV_CalcAndXorMasks(rop
, physDev
->penColor
, &physDev
->penAnd
, &physDev
->penXor
);
628 _DIBDRV_CalcAndXorMasks(rop
, physDev
->brushColor
, &physDev
->brushAnd
, &physDev
->brushXor
);
629 _DIBDRV_CalcAndXorMasks(rop
, physDev
->backgroundColor
, &physDev
->backgroundAnd
, &physDev
->backgroundXor
);
630 if(physDev
->brushAnds
)
632 HeapFree(GetProcessHeap(), 0, physDev
->brushAnds
);
633 HeapFree(GetProcessHeap(), 0, physDev
->brushXors
);
635 physDev
->brushAnds
= NULL
;
636 physDev
->brushXors
= NULL
;
640 /* note : X11 Driver don't have SetROP2() function exported */
643 /***********************************************************************
646 COLORREF
DIBDRV_SetBkColor( DIBDRVPHYSDEV
*physDev
, COLORREF color
)
650 MAYBE(TRACE("physDev:%p, color:%x\n", physDev
, color
));
654 physDev
->backgroundColor
= _DIBDRV_MapColor(physDev
, color
);
655 physDev
->backgroundColor
= physDev
->physBitmap
->funcs
->ColorToPixel(physDev
->physBitmap
, physDev
->backgroundColor
);
657 _DIBDRV_CalcAndXorMasks(physDev
->rop2
, physDev
->backgroundColor
, &physDev
->backgroundAnd
, &physDev
->backgroundXor
);
663 /* DDB selected in, use X11 driver */
664 res
= _DIBDRV_GetDisplayDriver()->pSetBkColor(physDev
->X11PhysDev
, color
);