DIB Engine: fixes against wine tests
[wine/hacks.git] / dlls / winedib.drv / graphics.c
blob8e2c12ee2ca1604dc82c4a8b1ae20e24994db5fd
1 /*
2 * DIBDRV implementation of GDI driver graphics functions
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);
28 static inline void OrderInt(int *i1, int *i2)
30 if(*i1 > *i2)
32 int tmp;
33 tmp = *i1;
34 *i1 = *i2;
35 *i2 = tmp;
39 #define LEFT_SIDE 1
40 #define TOP_SIDE 2
41 #define RIGHT_SIDE 4
42 #define BOTTOM_SIDE 8
44 /* clips a line segment by a rectangular window */
45 static inline BYTE outCodes(const POINT *p, const RECT *r)
47 BYTE Code = 0;
49 if(p->y < r->top)
50 Code |= TOP_SIDE;
51 else if(p->y >= r->bottom)
52 Code |= BOTTOM_SIDE;
53 if(p->x >= r->right)
54 Code |= RIGHT_SIDE;
55 else if(p->x < r->left)
56 Code |= LEFT_SIDE;
57 return Code;
60 static BOOL ClipLine(const POINT *p1, const POINT *p2, const RECT *r, POINT *pc1, POINT *pc2)
62 BYTE outCode1,outCode2;
63 int tmp;
64 BYTE tmpCode;
66 pc1->x = p1->x; pc1->y = p1->y;
67 pc2->x = p2->x; pc2->y = p2->y;
68 while(TRUE)
70 outCode1 = outCodes(pc1, r);
71 outCode2 = outCodes(pc2, r);
72 if(outCode1 & outCode2)
73 return FALSE;
74 if(!outCode1 && !outCode2)
75 return TRUE;
76 if(!outCode1)
78 tmp = pc1->x; pc1->x = pc2->x; pc2->x = tmp;
79 tmp = pc1->y; pc1->y = pc2->y; pc2->y = tmp;
80 tmpCode = outCode1; outCode1 = outCode2; outCode2 = tmpCode;
82 if(outCode1 & TOP_SIDE)
84 pc1->x += MulDiv(pc2->x - pc1->x, r->top - pc1->y, pc2->y - pc1->y);
85 pc1->y = r->top;
87 else if(outCode1 & BOTTOM_SIDE)
89 pc1->x += MulDiv(pc2->x - pc1->x, r->bottom - 1 - pc1->y, pc2->y - pc1->y);
90 pc1->y = r->bottom - 1;
92 else if(outCode1 & RIGHT_SIDE)
94 pc1->y += MulDiv(pc2->y - pc1->y, r->right - 1 - pc1->x, pc2->x - pc1->x);
95 pc1->x = r->right - 1;
97 else if(outCode1 & LEFT_SIDE)
99 pc1->y += MulDiv(pc2->y - pc1->y, r->left - pc1->x, pc2->x - pc1->x);
100 pc1->x = r->left;
105 /* Clips a polygon by an horizontal/vertical line
106 which indicates the side :
108 static inline BOOL PointInside(const POINT *p, const RECT *r, BYTE side)
110 switch(side)
112 case 1: /* left */
113 return p->x >= r->left;
114 case 2: /* top */
115 return p->y >= r->top;
116 case 4: /* right */
117 return p->x < r->right;
118 case 8: /* bottom */
119 return p->y < r->bottom;
120 default:
121 return FALSE;
125 static inline void SideIntersect(const POINT *p1, const POINT *p2, const RECT *r, BYTE side, POINT *inters)
127 switch( side )
129 case LEFT_SIDE: /* left */
130 inters->x = r->left;
131 inters->y = MulDiv(p2->y - p1->y, r->left - p1->x, p2->x - p1->x) + p1->y;
132 break;
133 case TOP_SIDE: /* top */
134 inters->x = MulDiv(p2->x - p1->x, r->top - p1->y, p2->y - p1->y) + p1->x;
135 inters->y = r->top;
136 break;
137 case RIGHT_SIDE: /* right */
138 inters->x = r->right - 1;
139 inters->y = MulDiv(p2->y - p1->y, r->right - 1 - p1->x, p2->x - p1->x) + p1->y;
140 break;
141 case BOTTOM_SIDE: /* bottom */
142 inters->x = MulDiv(p2->x - p1->x, r->bottom - 1 - p1->y, p2->y - p1->y) + p1->x;
143 inters->y = r->bottom - 1;
144 break;
145 default:
146 break;
151 static BOOL ClipPolygonBySide(const POINT *pt, int count, const RECT *r, BYTE side, POINT **clipped, int *clippedCount)
153 int iPoint;
154 const POINT *p1, *p2;
155 POINT *pOut;
157 if(!(*clipped = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT) * count * 2)))
158 return FALSE;
159 pOut = *clipped;
160 *clippedCount = 0;
162 p1 = pt + count - 1;
163 p2 = pt;
164 for(iPoint = 0 ; iPoint < count ; iPoint++)
166 if(PointInside(p2, r, side))
168 /* point p is "inside" */
169 if(!PointInside(p1, r, side))
171 /* p is "inside" and s is "outside" */
172 SideIntersect(p2, p1, r, side, pOut++);
173 (*clippedCount)++;
175 pOut->x = p2->x;
176 pOut->y = p2->y;
177 pOut++;
178 (*clippedCount)++;
180 else if(PointInside( p1, r, side ))
182 /* s is "inside" and p is "outside" */
183 SideIntersect(p1, p2, r, side, pOut++);
184 (*clippedCount)++;
186 p1 = p2++;
188 return *clippedCount;
192 /* Clips a polygon by a rectangular window - returns a new polygon */
193 static BOOL ClipPolygon(const POINT* pt, int count, const RECT *r, POINT **newPt, int *newCount)
195 POINT *pc1, *pc2;
196 int count1, count2;
197 BOOL res;
199 if(!ClipPolygonBySide(pt, count, r, LEFT_SIDE, &pc1, &count1))
200 return FALSE;
201 res = ClipPolygonBySide(pc1, count1, r, TOP_SIDE, &pc2, &count2);
202 HeapFree(GetProcessHeap(), 0, pc1);
203 if(!res)
204 return FALSE;
205 res = ClipPolygonBySide(pc2, count2, r, RIGHT_SIDE, &pc1, &count1);
206 HeapFree(GetProcessHeap(), 0, pc2);
207 if(!res)
208 return FALSE;
209 res = ClipPolygonBySide(pc1, count1, r, BOTTOM_SIDE, &pc2, &count2);
210 HeapFree(GetProcessHeap(), 0, pc1);
211 if(!res)
212 return FALSE;
214 *newPt = pc2;
215 *newCount = count2;
216 return TRUE;
219 /* Intersects a line given by 2 points with an horizontal scan line at height y */
220 static BOOL ScanLine(const POINT *p1, const POINT *p2, int ys, POINT *pRes)
222 if(!pRes)
223 return FALSE;
225 /* if line lies completely over or under scan line, no intersection */
226 if((p1->y < ys && p2->y < ys) || (p1->y >= ys && p2->y >= ys))
227 return FALSE;
229 /* if line is parallel to x axis, we consider it not intersecting */
230 if(p1->y == p2->y)
231 return FALSE;
233 pRes->x = MulDiv(p2->x - p1->x, ys - p1->y, p2->y - p1->y) + p1->x;
234 pRes->y = ys;
235 return TRUE;
238 /* Gets an x-ordered list of intersection points of a scanline at position y
239 with a polygon/polyline */
240 static BOOL ScanPolygon(const POINT *pt, int count, int ys, POINT **scans, int *scanCount)
242 const POINT *p1, *p2;
243 POINT *pDest;
244 int iPoint;
245 POINT *ps1, *ps2;
246 int i, j, tmp;
248 /* if not at least 2 points, nothing to return */
249 if(count < 2)
250 return FALSE;
252 /* intersections count is AT MOST 'count'; we don't care to
253 allocate exact memory needed */
254 *scans = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT)*count);
255 if(!*scans)
256 return FALSE;
258 /* builds unordered intersections */
259 pDest = *scans;
260 *scanCount = 0;
261 p2 = pt;
262 for(iPoint = 0; iPoint < count-1; iPoint++)
264 p1 = p2;
265 p2++;
266 if(ScanLine(p1, p2, ys, pDest))
268 pDest++;
269 (*scanCount)++;
272 p1 = p2;
273 p2 = pt;
274 if(ScanLine(p1, p2, ys, pDest))
276 pDest++;
277 (*scanCount)++;
280 /* now we sort the list -- duped point are left into
281 as they're needed for the scanline fill algorithm */
282 for(i = 0, ps1 = *scans; i < *scanCount -1; i++, ps1++)
283 for(j = i+1, ps2 = ps1+1; j < *scanCount; j++, ps2++)
284 if(ps2->x < ps1->x)
286 tmp = ps2->x;
287 ps2->x = ps1->x;
288 ps1->x = tmp;
289 tmp = ps2->y;
290 ps2->y = ps1->y;
291 ps1->y = tmp;
294 return TRUE;
297 /* gets bounding box of a polygon */
298 static void PolygonBoundingBox(const POINT *pt, int count, RECT *bBox)
300 const POINT *p;
301 int iPoint;
303 bBox->left = MAXLONG; bBox->right = -MAXLONG;
304 bBox->top = MAXLONG; bBox->bottom = -MAXLONG;
305 for(p = pt, iPoint = 0; iPoint < count; iPoint++, p++)
307 if(p->x < bBox->left ) bBox->left = p->x;
308 if(p->x > bBox->right ) bBox->right = p->x;
309 if(p->y < bBox->top ) bBox->top = p->y;
310 if(p->y > bBox->bottom) bBox->bottom = p->y;
314 /* intersect 2 rectangles (just to not use USER32 one...)
315 bottom and tight sides are considered OUTSIDE */
316 BOOL _DIBDRV_IntersectRect(RECT *d, const RECT *s1, const RECT *s2)
318 if(s1->right <= s2->left ||
319 s2->right <= s1->left ||
320 s1->bottom <= s2->top ||
321 s2->bottom <= s1->top
323 return FALSE;
324 d->left = s1->left > s2->left ? s1->left : s2->left;
325 d->top = s1->top > s2->top ? s1->top : s2->top;
326 d->right = s1->right < s2->right ? s1->right : s2->right;
327 d->bottom = s1->bottom < s2->bottom ? s1->bottom : s2->bottom;
328 return TRUE;
331 /* converts a rectangle form Word space to Device space */
332 void _DIBDRV_Rect_ws2ds(DIBDRVPHYSDEV *physDev, const RECT *src, RECT *dst)
334 POINT pts[2];
335 pts[0].x = src->left;
336 pts[0].y = src->top;
337 pts[1].x = src->right;
338 pts[1].y = src->bottom;
339 LPtoDP(physDev->hdc, pts, 2);
340 dst->left = pts[0].x;
341 dst->top = pts[0].y;
342 dst->right = pts[1].x;
343 dst->bottom = pts[1].y;
346 /* converts positions from Word space to Device space */
347 void _DIBDRV_Position_ws2ds(DIBDRVPHYSDEV *physDev, int *x, int *y)
349 POINT p;
350 p.x = *x;
351 p.y = *y;
352 LPtoDP(physDev->hdc, &p, 1);
353 *x = p.x;
354 *y = p.y;
357 void _DIBDRV_Positions_ws2ds(DIBDRVPHYSDEV *physDev, int *x1, int *y1, int *x2, int *y2)
359 POINT pts[2];
360 pts[0].x = *x1;
361 pts[0].y = *y1;
362 pts[1].x = *x2;
363 pts[1].y = *y2;
364 LPtoDP(physDev->hdc, pts, 2);
365 *x1 = pts[0].x;
366 *y1 = pts[0].y;
367 *x2 = pts[1].x;
368 *y2 = pts[1].y;
371 /* converts sizes from Word space to Device space */
372 void _DIBDRV_Sizes_ws2ds(DIBDRVPHYSDEV *physDev, int *w, int *h)
374 POINT pts[2];
375 pts[0].x = 0;
376 pts[0].y = 0;
377 pts[1].x = *w;
378 pts[1].y = *h;
379 LPtoDP(physDev->hdc, pts, 2);
380 *w = pts[1].x - pts[0].x;
381 *h = pts[1].y - pts[0].y;
384 /***********************************************************************
385 * DIBDRV_Arc
387 BOOL DIBDRV_Arc( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
388 int xstart, int ystart, int xend, int yend )
390 BOOL res;
392 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
393 physDev, left, top, right, bottom, xstart, ystart, xend, yend));
395 if(physDev->hasDIB)
397 /* DIB section selected in, use DIB Engine */
398 ONCE(FIXME("STUB\n"));
399 res = TRUE;
401 else
403 /* DDB selected in, use X11 driver */
404 res = _DIBDRV_GetDisplayDriver()->pArc(physDev->X11PhysDev, left, top, right, bottom,
405 xstart, ystart, xend, yend);
407 return res;
410 /***********************************************************************
411 * DIBDRV_Chord
413 BOOL DIBDRV_Chord( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
414 int xstart, int ystart, int xend, int yend )
416 BOOL res;
418 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
419 physDev, left, top, right, bottom, xstart, ystart, xend, yend));
421 if(physDev->hasDIB)
423 /* DIB section selected in, use DIB Engine */
424 ONCE(FIXME("STUB\n"));
425 res = TRUE;
427 else
429 /* DDB selected in, use X11 driver */
430 res = _DIBDRV_GetDisplayDriver()->pChord(physDev->X11PhysDev, left, top, right, bottom,
431 xstart, ystart, xend, yend);
433 return res;
436 /***********************************************************************
437 * DIBDRV_Ellipse
439 BOOL DIBDRV_Ellipse( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom )
441 BOOL res;
443 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d\n",
444 physDev, left, top, right, bottom));
446 if(physDev->hasDIB)
448 /* DIB section selected in, use DIB Engine */
449 ONCE(FIXME("STUB\n"));
450 res = TRUE;
452 else
454 /* DDB selected in, use X11 driver */
455 res = _DIBDRV_GetDisplayDriver()->pEllipse(physDev->X11PhysDev, left, top, right, bottom);
457 return res;
460 /**********************************************************************
461 * DIBDRV_ExtFloodFill
463 BOOL DIBDRV_ExtFloodFill( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color,
464 UINT fillType )
466 BOOL res;
468 MAYBE(TRACE("physDev:%p, x:%d, y:%d, color:%x, fillType:%d\n",
469 physDev, x, y, color, fillType));
471 if(physDev->hasDIB)
473 /* DIB section selected in, use DIB Engine */
474 ONCE(FIXME("STUB\n"));
475 res = TRUE;
477 else
479 /* DDB selected in, use X11 driver */
480 res = _DIBDRV_GetDisplayDriver()->pExtFloodFill(physDev->X11PhysDev, x, y, color, fillType);
482 return res;
485 /***********************************************************************
486 * DIBDRV_GetDCOrgEx
488 BOOL DIBDRV_GetDCOrgEx( DIBDRVPHYSDEV *physDev, LPPOINT lpp )
490 BOOL res;
492 MAYBE(TRACE("physDev:%p, lpp:%p\n", physDev, lpp));
494 if(physDev->hasDIB)
496 /* DIB section selected in, use DIB Engine */
497 ONCE(FIXME("STUB\n"));
498 res = TRUE;
500 else
502 /* DDB selected in, use X11 driver */
503 res = _DIBDRV_GetDisplayDriver()->pGetDCOrgEx(physDev->X11PhysDev, lpp);
505 return res;
508 /***********************************************************************
509 * DIBDRV_GetPixel
511 COLORREF DIBDRV_GetPixel( DIBDRVPHYSDEV *physDev, int x, int y )
513 COLORREF res;
515 MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
517 if(physDev->hasDIB)
519 _DIBDRV_Position_ws2ds(physDev, &x, &y);
520 res = physDev->physBitmap.funcs->GetPixel(&physDev->physBitmap, x, y);
522 else
524 /* DDB selected in, use X11 driver */
525 res = _DIBDRV_GetDisplayDriver()->pGetPixel(physDev->X11PhysDev, x, y);
527 return res;
530 /***********************************************************************
531 * DIBDRV_LineTo
533 BOOL DIBDRV_LineTo( DIBDRVPHYSDEV *physDev, int x, int y )
535 BOOL res;
536 POINT curPos;
537 RECT *r;
538 int iRec;
539 POINT p1, p2, pc1, pc2;
541 MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
543 if(physDev->hasDIB)
545 res = FALSE;
546 GetCurrentPositionEx(physDev->hdc, &curPos);
548 /* converts position to device space */
549 p1.x = curPos.x; p1.y = curPos.y;
550 p2.x = x; p2.y = y;
551 LPtoDP(physDev->hdc, &p1, 1);
552 LPtoDP(physDev->hdc, &p2, 1);
554 /* cycle on all current clipping rectangles */
555 r = physDev->regionRects;
556 for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++)
558 _DIBDRV_ResetDashOrigin(physDev);
560 /* clipe line on current region area */
561 if(ClipLine(&p1, &p2, r, &pc1, &pc2))
563 if(pc1.y == pc2.y)
564 physDev->penHLine(physDev, pc1.x, pc2.x, pc1.y);
565 else if(pc1.x == pc2.x)
566 physDev->penVLine(physDev, pc1.x, pc1.y, pc2.y);
567 else
568 physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
569 res = TRUE;
573 /* moves current position to next point */
574 MoveToEx(physDev->hdc, x, y, NULL);
576 else
578 /* DDB selected in, use X11 driver */
579 res = _DIBDRV_GetDisplayDriver()->pLineTo(physDev->X11PhysDev, x, y);
581 return res;
584 /***********************************************************************
585 * DIBDRV_PaintRgn
587 BOOL DIBDRV_Rectangle( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom);
588 BOOL DIBDRV_PaintRgn( DIBDRVPHYSDEV *physDev, HRGN hrgn )
590 BOOL res = FALSE;
591 int i;
592 RECT *rect;
593 RGNDATA *data;
594 int size;
596 MAYBE(TRACE("physDev:%p, hrgn:%p\n", physDev, hrgn));
598 if(physDev->hasDIB)
600 /* gets needed region data size */
601 if(!(size = GetRegionData(hrgn, 0, NULL)))
602 goto fin;
604 /* allocates buffer and gets actual region data */
605 if(!(data = HeapAlloc(GetProcessHeap(), 0, size)))
606 goto fin;
607 if(!GetRegionData(hrgn, size, data))
609 HeapFree(GetProcessHeap(), 0, data);
610 goto fin;
613 /* paints the filled rectangles */
614 rect = (RECT *)data->Buffer;
615 for(i = 0; i < data->rdh.nCount; i++)
617 DIBDRV_Rectangle( physDev, rect->left, rect->top, rect->right, rect->bottom);
618 rect++;
620 HeapFree( GetProcessHeap(), 0, data );
621 res = TRUE;
622 fin:
625 else
627 /* DDB selected in, use X11 driver */
628 res = _DIBDRV_GetDisplayDriver()->pPaintRgn(physDev->X11PhysDev, hrgn);
630 return res;
633 /***********************************************************************
634 * DIBDRV_Pie
636 BOOL DIBDRV_Pie( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
637 int xstart, int ystart, int xend, int yend )
639 BOOL res;
641 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
642 physDev, left, top, right, bottom, xstart, ystart, xend, yend));
644 if(physDev->hasDIB)
646 /* DIB section selected in, use DIB Engine */
647 ONCE(FIXME("STUB\n"));
648 res = TRUE;
650 else
652 /* DDB selected in, use X11 driver */
653 res = _DIBDRV_GetDisplayDriver()->pPie(physDev->X11PhysDev, left, top, right, bottom,
654 xstart, ystart, xend, yend);
656 return res;
659 /**********************************************************************
660 * DIBDRV_Polygon
662 BOOL DIBDRV_Polygon( DIBDRVPHYSDEV *physDev, const POINT* ptw, int count )
664 BOOL res;
665 POINT *pt;
666 RECT *r;
667 int iRec;
668 POINT *clipped;
669 int clippedCount;
670 RECT bBox;
671 int ys;
672 POINT *scans;
673 int scanCount, iScan;
674 const POINT *p1, *p2;
675 int iPoint;
676 POINT pc1, pc2;
678 MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, ptw, count));
680 if(physDev->hasDIB)
682 /* DIB section selected in, use DIB Engine */
684 res = FALSE;
686 /* first converts all points to device coords */
687 if(!(pt = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT) * count)))
688 goto fin;
689 memcpy(pt, ptw, sizeof(POINT) * count);
690 LPtoDP(physDev->hdc, pt, count);
692 /* cycle on all current clipping rectangles */
693 r = physDev->regionRects;
694 for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++)
696 /* filled area */
697 if(ClipPolygon(pt, count, r, &clipped, &clippedCount))
699 /* gets polygon bounding box -- for ytop and ybottom */
700 PolygonBoundingBox(clipped, clippedCount, &bBox);
702 /* gets all ordered intersections of polygon with
703 current scanline */
704 for(ys = bBox.top; ys < bBox.bottom; ys++)
706 if(ScanPolygon(clipped, clippedCount, ys, &scans, &scanCount))
708 if(scanCount >= 2)
710 res = TRUE;
711 p1 = scans;
712 p2 = p1+1;
713 iScan = 0;
714 while(iScan < scanCount - 1)
716 physDev->brushHLine(physDev, p1->x, p2->x, ys);
717 p1 +=2;
718 p2 +=2;
719 iScan +=2;
722 HeapFree(GetProcessHeap(), 0, scans);
725 HeapFree(GetProcessHeap(), 0, clipped);
728 /* perimeter -- don't use PolyLine for speed */
729 p2 = pt;
730 for(iPoint = 0; iPoint < count -1; iPoint++)
732 p1 = p2++;
733 if(ClipLine(p1, p2, r, &pc1, &pc2))
735 res = TRUE;
736 physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
739 p1 = p2;
740 p2 = pt;
741 if(ClipLine(p1, p2, r, &pc1, &pc2))
743 res = TRUE;
744 physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
748 HeapFree(GetProcessHeap(), 0, pt);
751 else
753 /* DDB selected in, use X11 driver */
754 res = _DIBDRV_GetDisplayDriver()->pPolygon(physDev->X11PhysDev, ptw, count);
756 fin:
757 return res;
760 /**********************************************************************
761 * DIBDRV_Polyline
763 BOOL DIBDRV_Polyline( DIBDRVPHYSDEV *physDev, const POINT* ptw, int count )
765 BOOL res;
767 MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, ptw, count));
769 if(physDev->hasDIB)
771 /* DIB section selected in, use DIB Engine */
772 POINT *pt;
773 RECT *r;
774 POINT pc1, pc2;
775 int iRec, iPoint;
777 if(count < 2)
778 return FALSE;
779 res = FALSE;
781 /* first converts all points to device coords */
782 if(!(pt = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT) * count)))
783 return FALSE;
784 memcpy(pt, ptw, sizeof(POINT) * count);
785 LPtoDP(physDev->hdc, pt, count);
787 r = physDev->regionRects;
788 for(iRec = 0; iRec < physDev->regionRectCount; iRec++)
790 const POINT *p2 = pt, *p1;
791 for(iPoint = 0; iPoint < count -1; iPoint++)
793 p1 = p2++;
794 if(ClipLine(p1, p2, r, &pc1, &pc2))
796 res = TRUE;
797 physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
800 r++;
803 HeapFree(GetProcessHeap(), 0, pt);
805 return res;
807 else
809 /* DDB selected in, use X11 driver */
810 res = _DIBDRV_GetDisplayDriver()->pPolyline(physDev->X11PhysDev, ptw, count);
812 return res;
815 /**********************************************************************
816 * DIBDRV_PolyPolygon
818 BOOL DIBDRV_PolyPolygon( DIBDRVPHYSDEV *physDev, const POINT* pt, const int* counts, UINT polygons)
820 BOOL res;
822 MAYBE(TRACE("physDev:%p, pt:%p, counts:%p, polygons:%d\n", physDev, pt, counts, polygons));
824 if(physDev->hasDIB)
826 /* DIB section selected in, use DIB Engine */
827 ONCE(FIXME("STUB\n"));
828 res = TRUE;
830 else
832 /* DDB selected in, use X11 driver */
833 res = _DIBDRV_GetDisplayDriver()->pPolyPolygon(physDev->X11PhysDev, pt, counts, polygons);
835 return res;
838 /**********************************************************************
839 * DIBDRV_PolyPolyline
841 BOOL DIBDRV_PolyPolyline( DIBDRVPHYSDEV *physDev, const POINT* pt, const DWORD* counts,
842 DWORD polylines )
844 BOOL res;
846 MAYBE(TRACE("physDev:%p, pt:%p, counts:%p, polylines:%d\n", physDev, pt, counts, polylines));
848 if(physDev->hasDIB)
850 /* DIB section selected in, use DIB Engine */
851 ONCE(FIXME("STUB\n"));
852 res = TRUE;
854 else
856 /* DDB selected in, use X11 driver */
857 res = _DIBDRV_GetDisplayDriver()->pPolyPolyline(physDev->X11PhysDev, pt, counts, polylines);
859 return res;
862 /***********************************************************************
863 * DIBDRV_Rectangle
865 BOOL DIBDRV_Rectangle( DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2)
867 BOOL res;
868 int i;
869 RECT rWorld, rDevice, rClipped;
870 RECT *r;
871 int iRec;
873 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d\n", physDev, x1, y1, x2, y2));
875 if(physDev->hasDIB)
877 res = FALSE;
879 OrderInt(&x1, &x2);
880 OrderInt(&y1, &y2);
882 /* converts to device space */
883 rWorld.left = x1; rWorld.top = y1; rWorld.right = x2; rWorld.bottom = y2;
884 _DIBDRV_Rect_ws2ds(physDev, &rWorld, &rDevice);
886 /* loop on all clip region rectangles */
887 r = physDev->regionRects;
888 for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++)
890 /* clips rectangle to current region */
891 if(_DIBDRV_IntersectRect(&rClipped, &rDevice, r))
893 x1 = rClipped.left; y1 = rClipped.top;
894 x2 = rClipped.right; y2 = rClipped.bottom;
896 _DIBDRV_ResetDashOrigin(physDev);
898 /* fill the inside, if not null brush */
899 if(physDev->brushStyle != BS_NULL)
901 if(x2 > x1)
902 for (i = y1; i < y2; i++)
903 physDev->brushHLine(physDev, x1, x2, i);
906 /* draw perimeter, if not null pen */
907 if(physDev->penStyle != PS_NULL)
910 /* particular case where the rectangle
911 degenerates to a line or a point */
912 if(x1 >= x2 - 1)
913 physDev->penVLine(physDev, x1, y1, y2);
914 else if (y1 >= y2 -1)
915 physDev->penHLine(physDev, x1, x2, y1);
916 else
918 /* Draw the perimeter */
919 physDev->penHLine(physDev, x1 , x2 , y1 );
920 physDev->penHLine(physDev, x1 , x2 , y2 - 1);
921 physDev->penVLine(physDev, x1 , y1 + 1, y2 - 1);
922 physDev->penVLine(physDev, x2 - 1, y1 + 1, y2 - 1);
925 res = TRUE;
929 else
931 /* DDB selected in, use X11 driver */
932 res = _DIBDRV_GetDisplayDriver()->pRectangle(physDev->X11PhysDev, x1, y1, x2, y2);
934 return res;
937 /***********************************************************************
938 * DIBDRV_RoundRect
940 BOOL DIBDRV_RoundRect( DIBDRVPHYSDEV *physDev, int left, int top, int right,
941 int bottom, int ell_width, int ell_height )
943 BOOL res;
945 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, ell_width:%d, ell_height:%d\n",
946 physDev, left, top, right, bottom, ell_width, ell_height));
948 if(physDev->hasDIB)
950 /* DIB section selected in, use DIB Engine */
951 ONCE(FIXME("STUB\n"));
952 res = TRUE;
954 else
956 /* DDB selected in, use X11 driver */
957 res = _DIBDRV_GetDisplayDriver()->pRoundRect(physDev->X11PhysDev, left, top, right, bottom,
958 ell_width, ell_height);
960 return res;
963 /***********************************************************************
964 * DIBDRV_SetPixel
966 COLORREF DIBDRV_SetPixel( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color )
968 COLORREF res;
969 DWORD and, xor;
971 MAYBE(TRACE("physDev:%p, x:%d, y:%d, color:%x\n", physDev, x, y, color));
973 if(physDev->hasDIB)
975 /* get real colorref */
976 color = _DIBDRV_MapColor(physDev, color);
978 /* map to pixel color / palette index */
979 color = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, color);
981 _DIBDRV_Position_ws2ds(physDev, &x, &y);
983 /* gets previous pixel */
984 res = physDev->physBitmap.funcs->GetPixel(&physDev->physBitmap, x, y);
986 /* calculates AND and XOR from color */
987 _DIBDRV_CalcAndXorMasks(GetROP2(physDev->hdc), color, &and, &xor);
989 /* sets the pixel */
990 physDev->physBitmap.funcs->SetPixel(&physDev->physBitmap, x, y, and, xor);
992 else
994 /* DDB selected in, use X11 driver */
995 res = _DIBDRV_GetDisplayDriver()->pSetPixel(physDev->X11PhysDev, x, y, color);
997 return res;
1000 /***********************************************************************
1001 * DIBDRV_SetDCOrg
1003 DWORD DIBDRV_SetDCOrg( DIBDRVPHYSDEV *physDev, int x, int y )
1005 DWORD res;
1007 MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
1009 if(physDev->hasDIB)
1011 /* DIB section selected in, use DIB Engine */
1012 ONCE(FIXME("STUB\n"));
1013 res = 0;
1015 else
1017 /* DDB selected in, use X11 driver */
1018 res = _DIBDRV_GetDisplayDriver()->pSetDCOrg(physDev->X11PhysDev, x, y);
1020 return res;