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
= _DIBDRV_MapColor(physDev
, logpen
.lopnColor
);
360 physDev
->penColor
= physDev
->physBitmap
.funcs
->ColorToPixel(&physDev
->physBitmap
, physDev
->penColorref
);
362 _DIBDRV_CalcAndXorMasks(GetROP2(physDev
->hdc
), physDev
->penColor
, &physDev
->penAnd
, &physDev
->penXor
);
364 physDev
->penStyle
= logpen
.lopnStyle
;
365 switch(logpen
.lopnStyle
)
368 ONCE(FIXME("Unhandled pen style %d\n", logpen
.lopnStyle
));
369 physDev
->penStyle
= PS_SOLID
;
372 physDev
->penHLine
= SolidPenHLine
;
373 physDev
->penVLine
= SolidPenVLine
;
374 physDev
->penLine
= SolidPenLine
;
375 physDev
->penPattern
= NULL
;
382 physDev
->penHLine
= DashedPenHLine
;
383 physDev
->penVLine
= DashedPenVLine
;
384 physDev
->penLine
= DashedPenLine
;
385 physDev
->penPattern
= &dashPatterns
[logpen
.lopnStyle
- PS_DASH
];
386 _DIBDRV_ResetDashOrigin(physDev
);
389 physDev
->penHLine
= NullPenHLine
;
390 physDev
->penVLine
= NullPenVLine
;
391 physDev
->penLine
= NullPenLine
;
392 physDev
->penPattern
= NULL
;
399 /* DDB selected in, use X11 driver */
400 res
= _DIBDRV_GetDisplayDriver()->pSelectPen(physDev
->X11PhysDev
, hpen
);
405 /***********************************************************************
406 * DIBDRV_SetDCPenColor
408 COLORREF
DIBDRV_SetDCPenColor( DIBDRVPHYSDEV
*physDev
, COLORREF crColor
)
412 MAYBE(TRACE("physDev:%p, crColor:%x\n", physDev
, crColor
));
416 /* DIB section selected in, use DIB Engine */
417 ONCE(FIXME("STUB\n"));
422 /* DDB selected in, use X11 driver */
423 res
= _DIBDRV_GetDisplayDriver()->pSetDCPenColor(physDev
->X11PhysDev
, crColor
);
428 /***********************************************************************
431 HBRUSH
DIBDRV_SelectBrush( DIBDRVPHYSDEV
*physDev
, HBRUSH hbrush
)
437 MAYBE(TRACE("physDev:%p, hbrush:%p\n", physDev
, hbrush
));
441 GetObjectW(hbrush
, sizeof(logbrush
), &logbrush
);
443 /* frees any currently selected DIB brush and cache */
444 _DIBDRVBITMAP_Free(&physDev
->brushBitmap
);
445 _DIBDRVBITMAP_Free(&physDev
->brushBmpCache
);
446 if(physDev
->brushAnds
)
448 HeapFree(GetProcessHeap(), 0, physDev
->brushAnds
);
449 HeapFree(GetProcessHeap(), 0, physDev
->brushXors
);
451 physDev
->brushAnds
= NULL
;
452 physDev
->brushXors
= NULL
;
454 switch (logbrush
.lbStyle
)
457 FIXME("Unhandled brush style %d\n", logbrush
.lbStyle
);
458 physDev
->brushColorref
= 0;
462 physDev
->brushColorref
= _DIBDRV_MapColor(physDev
, logbrush
.lbColor
);
464 MAYBE(TRACE("SOLID Pattern -- color is %x\n", physDev
->brushColorref
));
465 physDev
->brushStyle
= BS_SOLID
;
466 physDev
->brushHLine
= SolidBrushHLine
;
468 physDev
->brushColor
= physDev
->physBitmap
.funcs
->ColorToPixel(&physDev
->physBitmap
, physDev
->brushColorref
);
470 _DIBDRV_CalcAndXorMasks(physDev
->rop2
, physDev
->brushColor
,
471 &physDev
->brushAnd
, &physDev
->brushXor
);
473 /* set the physDev brush style */
474 physDev
->brushStyle
= BS_SOLID
;
475 physDev
->isBrushBitmap
= FALSE
;
479 case BS_DIBPATTERN8X8
:
485 FIXME("DIB Pattern\n");
487 /* if no DIB selected in, fallback to null brush */
488 if(!physDev
->physBitmap
.bits
)
490 physDev
->brushColorref
= 0;
494 /* gets brush DIB's pointer */
495 bmi
= GlobalLock16(logbrush
.lbHatch
);
497 /* initializes a temporary DIB with brush's one */
498 if(!_DIBDRVBITMAP_InitFromBitmapinfo(&src
, bmi
))
500 ERR("Failed to initialize brush DIB\n");
505 /* converts brush bitmap to match currently selected one's format */
506 if(!_DIBDRVBITMAP_Convert(&physDev
->brushBitmap
, &src
, &physDev
->physBitmap
))
508 ERR("Failed to convert brush DIB\n");
509 _DIBDRVBITMAP_Free(&src
);
514 /* frees temporary DIB's data */
515 _DIBDRVBITMAP_Free(&src
);
517 /* use DIB pattern for brush lines */
518 physDev
->brushHLine
= PatternBrushHLine
;
521 /* frees brush's DIB pointer */
522 GlobalUnlock16(logbrush
.lbHatch
);
526 case BS_DIBPATTERNPT
:
527 FIXME("BS_DIBPATTERNPT not supported\n");
528 physDev
->brushColorref
= 0;
532 FIXME("BS_HATCHED not supported\n");
533 physDev
->brushColorref
= 0;
538 MAYBE(TRACE("NULL Pattern\n"));
539 physDev
->brushColorref
= 0;
540 physDev
->brushColor
= physDev
->physBitmap
.funcs
->ColorToPixel(&physDev
->physBitmap
, 0);
541 physDev
->brushHLine
= NullBrushHLine
;
547 FIXME("BS_PATTERN not supported\n");
548 physDev
->brushColorref
= 0;
552 MAYBE(TRACE("END\n"));
557 /* DDB selected in, use X11 driver */
559 /* we must check if a DIB pattern is requested */
560 GetObjectW(hbrush
, sizeof(logbrush
), &logbrush
);
561 switch (logbrush
.lbStyle
)
563 case BS_DIBPATTERN8X8
:
565 case BS_DIBPATTERNPT
:
566 FIXME("A DIB pattern was requested for a DDB bitmap\n");
577 res
= _DIBDRV_GetDisplayDriver()->pSelectBrush(physDev
->X11PhysDev
, hbrush
);
582 /***********************************************************************
583 * DIBDRV_SetDCBrushColor
585 COLORREF
DIBDRV_SetDCBrushColor( DIBDRVPHYSDEV
*physDev
, COLORREF crColor
)
589 MAYBE(TRACE("physDev:%p, crColor:%x\n", physDev
, crColor
));
593 /* DIB section selected in, use DIB Engine */
594 ONCE(FIXME("STUB\n"));
599 /* DDB selected in, use X11 driver */
600 res
= _DIBDRV_GetDisplayDriver()->pSetDCBrushColor(physDev
->X11PhysDev
, crColor
);
605 /***********************************************************************
608 int DIBDRV_SetROP2( DIBDRVPHYSDEV
*physDev
, int rop
)
612 MAYBE(TRACE("physDev:%p, rop:%x\n", physDev
, rop
));
614 prevRop
= physDev
->rop2
;
619 _DIBDRV_CalcAndXorMasks(rop
, physDev
->penColor
, &physDev
->penAnd
, &physDev
->penXor
);
620 _DIBDRV_CalcAndXorMasks(rop
, physDev
->brushColor
, &physDev
->brushAnd
, &physDev
->brushXor
);
621 _DIBDRV_CalcAndXorMasks(rop
, physDev
->backgroundColor
, &physDev
->backgroundAnd
, &physDev
->backgroundXor
);
622 if(physDev
->brushAnds
)
624 HeapFree(GetProcessHeap(), 0, physDev
->brushAnds
);
625 HeapFree(GetProcessHeap(), 0, physDev
->brushXors
);
627 physDev
->brushAnds
= NULL
;
628 physDev
->brushXors
= NULL
;
632 /* note : X11 Driver don't have SetROP2() function exported */
635 /***********************************************************************
638 COLORREF
DIBDRV_SetBkColor( DIBDRVPHYSDEV
*physDev
, COLORREF color
)
642 MAYBE(TRACE("physDev:%p, color:%x\n", physDev
, color
));
646 physDev
->backgroundColor
= _DIBDRV_MapColor(physDev
, color
);
647 physDev
->backgroundColor
= physDev
->physBitmap
.funcs
->ColorToPixel(&physDev
->physBitmap
, physDev
->backgroundColor
);
649 _DIBDRV_CalcAndXorMasks(physDev
->rop2
, physDev
->backgroundColor
, &physDev
->backgroundAnd
, &physDev
->backgroundXor
);
655 /* DDB selected in, use X11 driver */
656 res
= _DIBDRV_GetDisplayDriver()->pSetBkColor(physDev
->X11PhysDev
, color
);