31c9cd28adfe66dacc42b69a2168428f4c3b9f71
[wine/hacks.git] / dlls / winedib.drv / pen_brush.c
blob31c9cd28adfe66dacc42b69a2168428f4c3b9f71
1 /*
2 * DIBDRV pen objects
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include "dibdrv.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
29 static const DASHPATTERN dashPatterns[4] =
31 {2, {18, 6}},
32 {2, {3, 3}},
33 {4, {9, 6, 3, 6}},
34 {6, {9, 3, 3, 3, 3, 3}}
37 static inline void OrderEndPoints(int *s, int *e)
39 if(*s > *e)
41 int tmp;
42 tmp = *s + 1;
43 *s = *e + 1;
44 *e = tmp;
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);
65 return;
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;
85 else
87 *and = 0xffffffff;
88 *xor = 0;
92 static inline void NextDash(DIBDRVPHYSDEV *physDev)
94 if(physDev->leftInDash != 0)
95 return;
97 physDev->curDash++;
98 if(physDev->curDash == physDev->penPattern->count)
99 physDev->curDash = 0;
100 physDev->leftInDash = physDev->penPattern->dashes[physDev->curDash];
101 if(physDev->markSpace == mark)
102 physDev->markSpace = space;
103 else
104 physDev->markSpace = mark;
107 static void DashedPenHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
109 int x = x1;
110 DWORD and, xor;
111 DWORD dashLen;
113 if(x1 <= x2)
115 while(x != x2)
117 GetDashColors(physDev, &and, &xor);
119 dashLen = physDev->leftInDash;
120 if(x + dashLen > x2)
121 dashLen = x2 - x;
123 physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x, x + dashLen, y, and, xor);
124 x += dashLen;
126 physDev->leftInDash -= dashLen;
127 NextDash(physDev);
130 else
132 while(x != x2)
134 GetDashColors(physDev, &and, &xor);
136 dashLen = physDev->leftInDash;
137 if(x - (int)dashLen < x2)
138 dashLen = x - x2;
140 physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x - dashLen + 1, x + 1, y, and, xor);
141 x -= dashLen;
143 physDev->leftInDash -= dashLen;
144 NextDash(physDev);
149 static void DashedPenVLine(DIBDRVPHYSDEV *physDev, int x, int y1, int y2)
151 int y = y1;
152 DWORD and, xor;
153 DWORD dashLen;
155 if(y1 <= y2)
157 while(y != y2)
159 GetDashColors(physDev, &and, &xor);
161 dashLen = physDev->leftInDash;
162 if(y + dashLen > y2)
163 dashLen = y2 - y;
165 physDev->physBitmap.funcs->SolidVLine(&physDev->physBitmap, x, y, y + dashLen, and, xor);
166 y += dashLen;
168 physDev->leftInDash -= dashLen;
169 NextDash(physDev);
172 else
174 while(y != y2)
176 GetDashColors(physDev, &and, &xor);
178 dashLen = physDev->leftInDash;
179 if(y - (int)dashLen < y2)
180 dashLen = y - y2;
182 physDev->physBitmap.funcs->SolidVLine(&physDev->physBitmap, x, y - dashLen + 1, y + 1, and, xor);
183 y -= dashLen;
185 physDev->leftInDash -= dashLen;
186 NextDash(physDev);
191 static void WINAPI DashedPenLineCallback(int x, int y, LPARAM lparam)
193 DIBDRVPHYSDEV *physDev = (DIBDRVPHYSDEV *)lparam;
194 DWORD and, xor;
196 GetDashColors(physDev, &and, &xor);
198 physDev->physBitmap.funcs->SetPixel(&physDev->physBitmap, x, y, and, xor);
200 physDev->leftInDash--;
201 NextDash(physDev);
203 return;
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)
233 return 1;
234 return 0;
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;
269 and_ptr = *and;
270 xor_ptr = *xor;
272 while(size)
274 _DIBDRV_CalcAndXorMasks(rop, *color_ptr++, and_ptr++, xor_ptr++);
275 size -= 4;
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 /***********************************************************************
294 * DIBDRV_SelectPen
296 HPEN DIBDRV_SelectPen( DIBDRVPHYSDEV *physDev, HPEN hpen )
298 HPEN res;
299 LOGPEN logpen;
301 MAYBE(TRACE("physDev:%p, hpen:%p\n", physDev, hpen));
303 if(physDev->hasDIB)
305 GetObjectW(hpen, sizeof(logpen), &logpen);
307 physDev->penColorref = logpen.lopnColor;
309 if(physDev->physBitmap.bitCount == 1)
310 FixupFgColors1(physDev);
311 else
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)
318 default:
319 ONCE(FIXME("Unhandled pen style %d\n", logpen.lopnStyle));
320 /* fall through */
321 case PS_SOLID:
322 physDev->penHLine = SolidPenHLine;
323 physDev->penVLine = SolidPenVline;
324 physDev->penLine = SolidPenLine;
325 physDev->penPattern = NULL;
326 break;
328 case PS_DASH:
329 case PS_DOT:
330 case PS_DASHDOT:
331 case PS_DASHDOTDOT:
332 physDev->penHLine = DashedPenHLine;
333 physDev->penVLine = DashedPenVLine;
334 physDev->penLine = DashedPenLine;
335 physDev->penPattern = &dashPatterns[logpen.lopnStyle - PS_DASH];
336 _DIBDRV_ResetDashOrigin(physDev);
337 break;
339 res = hpen;
341 else
343 /* DDB selected in, use X11 driver */
344 res = _DIBDRV_GetDisplayDriver()->pSelectPen(physDev->X11PhysDev, hpen);
346 return res;
349 /***********************************************************************
350 * DIBDRV_SetDCPenColor
352 COLORREF DIBDRV_SetDCPenColor( DIBDRVPHYSDEV *physDev, COLORREF crColor )
354 COLORREF res;
356 MAYBE(TRACE("physDev:%p, crColor:%x\n", physDev, crColor));
358 if(physDev->hasDIB)
360 /* DIB section selected in, use DIB Engine */
361 ONCE(FIXME("STUB\n"));
362 res = crColor;
364 else
366 /* DDB selected in, use X11 driver */
367 res = _DIBDRV_GetDisplayDriver()->pSetDCPenColor(physDev->X11PhysDev, crColor);
369 return res;
372 /***********************************************************************
373 * DIBDRV_SelectBrush
375 HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush )
377 HBRUSH res = hbrush;
378 LOGBRUSH logbrush;
381 MAYBE(TRACE("physDev:%p, hbrush:%p\n", physDev, hbrush));
383 if(physDev->hasDIB)
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)
400 default:
401 FIXME("Unhandled brush style %d\n", logbrush.lbStyle);
402 physDev->brushColorref = 0;
403 goto solid;
405 case BS_SOLID:
406 physDev->brushColorref = logbrush.lbColor;
407 solid:
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);
414 else
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;
424 break;
426 case BS_DIBPATTERN8X8:
427 case BS_DIBPATTERN:
429 DIBDRVBITMAP src;
430 BITMAPINFO *bmi;
432 FIXME("DIB Pattern\n");
434 /* if no DIB selected in, fallback to null brush */
435 if(!physDev->physBitmap.bits)
437 physDev->brushColorref = 0;
438 goto solid;
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");
448 res = 0;
449 goto err;
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);
457 res = 0;
458 goto err;
461 /* frees temporary DIB's data */
462 _DIBDRVBITMAP_Free(&src);
464 /* use DIB pattern for brush lines */
465 physDev->brushHLine = PatternBrushHLine;
467 err:
468 /* frees brush's DIB pointer */
469 GlobalUnlock16(logbrush.lbHatch);
471 break;
473 case BS_DIBPATTERNPT:
474 FIXME("BS_DIBPATTERNPT not supported\n");
475 physDev->brushColorref = 0;
476 goto solid;
478 case BS_HATCHED:
479 FIXME("BS_HATCHED not supported\n");
480 physDev->brushColorref = 0;
481 goto solid;
483 case BS_NULL:
485 MAYBE(TRACE("NULL Pattern\n"));
486 physDev->brushColorref = 0;
487 goto solid;
490 case BS_PATTERN:
491 case BS_PATTERN8X8:
492 FIXME("BS_PATTERN not supported\n");
493 physDev->brushColorref = 0;
494 goto solid;
497 MAYBE(TRACE("END\n"));
498 return hbrush;
500 else
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:
509 case BS_DIBPATTERN:
510 case BS_DIBPATTERNPT:
511 FIXME("A DIB pattern was requested for a DDB bitmap\n");
512 break;
514 case BS_SOLID:
515 case BS_HATCHED:
516 case BS_NULL:
517 case BS_PATTERN:
518 case BS_PATTERN8X8:
519 default:
520 break;
522 res = _DIBDRV_GetDisplayDriver()->pSelectBrush(physDev->X11PhysDev, hbrush);
524 return res;
527 /***********************************************************************
528 * DIBDRV_SetDCBrushColor
530 COLORREF DIBDRV_SetDCBrushColor( DIBDRVPHYSDEV *physDev, COLORREF crColor )
532 COLORREF res;
534 MAYBE(TRACE("physDev:%p, crColor:%x\n", physDev, crColor));
536 if(physDev->hasDIB)
538 /* DIB section selected in, use DIB Engine */
539 ONCE(FIXME("STUB\n"));
540 res = crColor;
542 else
544 /* DDB selected in, use X11 driver */
545 res = _DIBDRV_GetDisplayDriver()->pSetDCBrushColor(physDev->X11PhysDev, crColor);
547 return res;
550 /***********************************************************************
551 * SetROP2
553 int DIBDRV_SetROP2( DIBDRVPHYSDEV *physDev, int rop )
555 int prevRop;
557 MAYBE(TRACE("physDev:%p, rop:%x\n", physDev, rop));
559 prevRop = physDev->rop2;
560 physDev->rop2 = rop;
562 if(prevRop != rop)
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;
576 return prevRop;
577 /* note : X11 Driver don't have SetROP2() function exported */
580 /***********************************************************************
581 * SetBkColor
583 COLORREF DIBDRV_SetBkColor( DIBDRVPHYSDEV *physDev, COLORREF color )
585 COLORREF res;
587 MAYBE(TRACE("physDev:%p, color:%x\n", physDev, color));
589 if(physDev->hasDIB)
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);
597 res = TRUE;
599 else
601 /* DDB selected in, use X11 driver */
602 res = _DIBDRV_GetDisplayDriver()->pSetBkColor(physDev->X11PhysDev, color);
604 return res;