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 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
*fore
= physDev
->physBitmap
.colorTable
+1;
227 if((color
& 0x00ffffff) == 0x00ffffff ||
229 fore
->rgbRed
== GetRValue(color
) &&
230 fore
->rgbGreen
== GetGValue(color
) &&
231 fore
->rgbBlue
== GetBValue(color
)
237 static void FixupFgColors1(DIBDRVPHYSDEV
*physDev
)
239 int rop
= GetROP2(physDev
->hdc
);
241 physDev
->penColor
= AdjustFgColor(physDev
, physDev
->penColorref
);
242 physDev
->brushColor
= AdjustFgColor(physDev
, physDev
->brushColorref
);
244 _DIBDRV_CalcAndXorMasks(rop
, physDev
->penColor
, &physDev
->penAnd
, &physDev
->penXor
);
245 _DIBDRV_CalcAndXorMasks(rop
, physDev
->brushColor
, &physDev
->brushAnd
, &physDev
->brushXor
);
246 HeapFree(GetProcessHeap(), 0, physDev
->brushAnds
);
247 HeapFree(GetProcessHeap(), 0, physDev
->brushXors
);
248 physDev
->brushAnds
= NULL
;
249 physDev
->brushXors
= NULL
;
252 static void SolidBrushHLine(DIBDRVPHYSDEV
*physDev
, int x1
, int x2
, int y
)
254 OrderEndPoints(&x1
, &x2
);
255 physDev
->physBitmap
.funcs
->SolidHLine(&physDev
->physBitmap
, x1
, x2
, y
, physDev
->brushAnd
, physDev
->brushXor
);
259 static void GenerateMasks(DIBDRVPHYSDEV
*physDev
, DIBDRVBITMAP
*bmp
, DWORD
**and, DWORD
**xor)
261 int rop
= GetROP2(physDev
->hdc
);
262 DWORD
*color_ptr
, *and_ptr
, *xor_ptr
;
263 DWORD size
= bmp
->height
* abs(bmp
->stride
);
265 *and = HeapAlloc(GetProcessHeap(), 0, size
);
266 *xor = HeapAlloc(GetProcessHeap(), 0, size
);
268 color_ptr
= bmp
->bits
;
274 _DIBDRV_CalcAndXorMasks(rop
, *color_ptr
++, and_ptr
++, xor_ptr
++);
279 static void PatternBrushHLine(DIBDRVPHYSDEV
*physDev
, int x1
, int x2
, int y
)
281 DWORD
*and, *xor, brushY
= y
% physDev
->brushBitmap
.height
;
283 if(!physDev
->brushAnds
)
284 GenerateMasks(physDev
, &physDev
->brushBitmap
, &physDev
->brushAnds
, &physDev
->brushXors
);
286 OrderEndPoints(&x1
, &x2
);
287 and = (DWORD
*)((char *)physDev
->brushAnds
+ brushY
* physDev
->brushBitmap
.stride
);
288 xor = (DWORD
*)((char *)physDev
->brushXors
+ brushY
* physDev
->brushBitmap
.stride
);
290 physDev
->physBitmap
.funcs
->PatternHLine(&physDev
->physBitmap
, x1
, x2
, y
, and, xor, physDev
->brushBitmap
.width
, x1
% physDev
->brushBitmap
.width
);
293 /***********************************************************************
296 HPEN
DIBDRV_SelectPen( DIBDRVPHYSDEV
*physDev
, HPEN hpen
)
301 MAYBE(TRACE("physDev:%p, hpen:%p\n", physDev
, hpen
));
305 GetObjectW(hpen
, sizeof(logpen
), &logpen
);
307 physDev
->penColorref
= logpen
.lopnColor
;
309 if(physDev
->physBitmap
.bitCount
== 1)
310 FixupFgColors1(physDev
);
312 physDev
->penColor
= physDev
->physBitmap
.funcs
->ColorToPixel(&physDev
->physBitmap
, logpen
.lopnColor
);
314 _DIBDRV_CalcAndXorMasks(GetROP2(physDev
->hdc
), physDev
->penColor
, &physDev
->penAnd
, &physDev
->penXor
);
316 switch(logpen
.lopnStyle
)
319 ONCE(FIXME("Unhandled pen style %d\n", logpen
.lopnStyle
));
322 physDev
->penHLine
= SolidPenHLine
;
323 physDev
->penVLine
= SolidPenVline
;
324 physDev
->penLine
= SolidPenLine
;
325 physDev
->penPattern
= NULL
;
332 physDev
->penHLine
= DashedPenHLine
;
333 physDev
->penVLine
= DashedPenVLine
;
334 physDev
->penLine
= DashedPenLine
;
335 physDev
->penPattern
= &dashPatterns
[logpen
.lopnStyle
- PS_DASH
];
336 _DIBDRV_ResetDashOrigin(physDev
);
343 /* DDB selected in, use X11 driver */
344 res
= _DIBDRV_GetDisplayDriver()->pSelectPen(physDev
->X11PhysDev
, hpen
);
349 /***********************************************************************
350 * DIBDRV_SetDCPenColor
352 COLORREF
DIBDRV_SetDCPenColor( DIBDRVPHYSDEV
*physDev
, COLORREF crColor
)
356 MAYBE(TRACE("physDev:%p, crColor:%x\n", physDev
, crColor
));
360 /* DIB section selected in, use DIB Engine */
361 ONCE(FIXME("STUB\n"));
366 /* DDB selected in, use X11 driver */
367 res
= _DIBDRV_GetDisplayDriver()->pSetDCPenColor(physDev
->X11PhysDev
, crColor
);
372 /***********************************************************************
375 HBRUSH
DIBDRV_SelectBrush( DIBDRVPHYSDEV
*physDev
, HBRUSH hbrush
)
381 MAYBE(TRACE("physDev:%p, hbrush:%p\n", physDev
, hbrush
));
385 GetObjectW(hbrush
, sizeof(logbrush
), &logbrush
);
387 /* frees any currently selected DIB brush and cache */
388 _DIBDRVBITMAP_Free(&physDev
->brushBitmap
);
389 _DIBDRVBITMAP_Free(&physDev
->brushBmpCache
);
390 if(physDev
->brushAnds
)
392 HeapFree(GetProcessHeap(), 0, physDev
->brushAnds
);
393 HeapFree(GetProcessHeap(), 0, physDev
->brushXors
);
395 physDev
->brushAnds
= NULL
;
396 physDev
->brushXors
= NULL
;
398 switch (logbrush
.lbStyle
)
401 FIXME("Unhandled brush style %d\n", logbrush
.lbStyle
);
402 physDev
->brushColorref
= 0;
406 physDev
->brushColorref
= logbrush
.lbColor
;
408 MAYBE(TRACE("SOLID Pattern -- color is %x\n", physDev
->brushColorref
));
409 physDev
->brushStyle
= BS_SOLID
;
410 physDev
->brushHLine
= SolidBrushHLine
;
412 if(physDev
->physBitmap
.bitCount
== 1)
413 FixupFgColors1(physDev
);
415 physDev
->brushColor
= physDev
->physBitmap
.funcs
->ColorToPixel(&physDev
->physBitmap
, logbrush
.lbColor
);
417 _DIBDRV_CalcAndXorMasks(physDev
->rop2
, physDev
->brushColor
,
418 &physDev
->brushAnd
, &physDev
->brushXor
);
420 /* set the physDev brush style */
421 physDev
->brushStyle
= BS_SOLID
;
422 physDev
->isBrushBitmap
= FALSE
;
426 case BS_DIBPATTERN8X8
:
432 FIXME("DIB Pattern\n");
434 /* if no DIB selected in, fallback to null brush */
435 if(!physDev
->physBitmap
.bits
)
437 physDev
->brushColorref
= 0;
441 /* gets brush DIB's pointer */
442 bmi
= GlobalLock16(logbrush
.lbHatch
);
444 /* initializes a temporary DIB with brush's one */
445 if(!_DIBDRVBITMAP_InitFromBitmapinfo(&src
, bmi
))
447 ERR("Failed to initialize brush DIB\n");
452 /* converts brush bitmap to match currently selected one's format */
453 if(!_DIBDRVBITMAP_Convert(&physDev
->brushBitmap
, &src
, &physDev
->physBitmap
))
455 ERR("Failed to convert brush DIB\n");
456 _DIBDRVBITMAP_Free(&src
);
461 /* frees temporary DIB's data */
462 _DIBDRVBITMAP_Free(&src
);
464 /* use DIB pattern for brush lines */
465 physDev
->brushHLine
= PatternBrushHLine
;
468 /* frees brush's DIB pointer */
469 GlobalUnlock16(logbrush
.lbHatch
);
473 case BS_DIBPATTERNPT
:
474 FIXME("BS_DIBPATTERNPT not supported\n");
475 physDev
->brushColorref
= 0;
479 FIXME("BS_HATCHED not supported\n");
480 physDev
->brushColorref
= 0;
485 MAYBE(TRACE("NULL Pattern\n"));
486 physDev
->brushColorref
= 0;
492 FIXME("BS_PATTERN not supported\n");
493 physDev
->brushColorref
= 0;
497 MAYBE(TRACE("END\n"));
502 /* DDB selected in, use X11 driver */
504 /* we must check if a DIB pattern is requested */
505 GetObjectW(hbrush
, sizeof(logbrush
), &logbrush
);
506 switch (logbrush
.lbStyle
)
508 case BS_DIBPATTERN8X8
:
510 case BS_DIBPATTERNPT
:
511 FIXME("A DIB pattern was requested for a DDB bitmap\n");
522 res
= _DIBDRV_GetDisplayDriver()->pSelectBrush(physDev
->X11PhysDev
, hbrush
);
527 /***********************************************************************
528 * DIBDRV_SetDCBrushColor
530 COLORREF
DIBDRV_SetDCBrushColor( DIBDRVPHYSDEV
*physDev
, COLORREF crColor
)
534 MAYBE(TRACE("physDev:%p, crColor:%x\n", physDev
, crColor
));
538 /* DIB section selected in, use DIB Engine */
539 ONCE(FIXME("STUB\n"));
544 /* DDB selected in, use X11 driver */
545 res
= _DIBDRV_GetDisplayDriver()->pSetDCBrushColor(physDev
->X11PhysDev
, crColor
);
550 /***********************************************************************
553 int DIBDRV_SetROP2( DIBDRVPHYSDEV
*physDev
, int rop
)
557 MAYBE(TRACE("physDev:%p, rop:%x\n", physDev
, rop
));
559 prevRop
= physDev
->rop2
;
564 _DIBDRV_CalcAndXorMasks(rop
, physDev
->penColor
, &physDev
->penAnd
, &physDev
->penXor
);
565 _DIBDRV_CalcAndXorMasks(rop
, physDev
->brushColor
, &physDev
->brushAnd
, &physDev
->brushXor
);
566 _DIBDRV_CalcAndXorMasks(rop
, physDev
->backgroundColor
, &physDev
->backgroundAnd
, &physDev
->backgroundXor
);
567 if(physDev
->brushAnds
)
569 HeapFree(GetProcessHeap(), 0, physDev
->brushAnds
);
570 HeapFree(GetProcessHeap(), 0, physDev
->brushXors
);
572 physDev
->brushAnds
= NULL
;
573 physDev
->brushXors
= NULL
;
577 /* note : X11 Driver don't have SetROP2() function exported */
580 /***********************************************************************
583 COLORREF
DIBDRV_SetBkColor( DIBDRVPHYSDEV
*physDev
, COLORREF color
)
587 MAYBE(TRACE("physDev:%p, color:%x\n", physDev
, color
));
591 physDev
->backgroundColor
= physDev
->physBitmap
.funcs
->ColorToPixel(&physDev
->physBitmap
, color
);
593 if(physDev
->physBitmap
.bitCount
== 1)
594 FixupFgColors1(physDev
);
595 _DIBDRV_CalcAndXorMasks(physDev
->rop2
, physDev
->backgroundColor
, &physDev
->backgroundAnd
, &physDev
->backgroundXor
);
601 /* DDB selected in, use X11 driver */
602 res
= _DIBDRV_GetDisplayDriver()->pSetBkColor(physDev
->X11PhysDev
, color
);