DIB Engine: Implement Polygon
[wine/hacks.git] / dlls / winedib.drv / graphics.c
blobfba34f5f31a4f8d076227e893e78b7e79b17474b
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->bottom;
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 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 /***********************************************************************
315 * DIBDRV_Arc
317 BOOL DIBDRV_Arc( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
318 int xstart, int ystart, int xend, int yend )
320 BOOL res;
322 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
323 physDev, left, top, right, bottom, xstart, ystart, xend, yend));
325 if(physDev->hasDIB)
327 /* DIB section selected in, use DIB Engine */
328 ONCE(FIXME("STUB\n"));
329 res = TRUE;
331 else
333 /* DDB selected in, use X11 driver */
334 res = _DIBDRV_GetDisplayDriver()->pArc(physDev->X11PhysDev, left, top, right, bottom,
335 xstart, ystart, xend, yend);
337 return res;
340 /***********************************************************************
341 * DIBDRV_Chord
343 BOOL DIBDRV_Chord( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
344 int xstart, int ystart, int xend, int yend )
346 BOOL res;
348 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
349 physDev, left, top, right, bottom, xstart, ystart, xend, yend));
351 if(physDev->hasDIB)
353 /* DIB section selected in, use DIB Engine */
354 ONCE(FIXME("STUB\n"));
355 res = TRUE;
357 else
359 /* DDB selected in, use X11 driver */
360 res = _DIBDRV_GetDisplayDriver()->pChord(physDev->X11PhysDev, left, top, right, bottom,
361 xstart, ystart, xend, yend);
363 return res;
366 /***********************************************************************
367 * DIBDRV_Ellipse
369 BOOL DIBDRV_Ellipse( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom )
371 BOOL res;
373 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d\n",
374 physDev, left, top, right, bottom));
376 if(physDev->hasDIB)
378 /* DIB section selected in, use DIB Engine */
379 ONCE(FIXME("STUB\n"));
380 res = TRUE;
382 else
384 /* DDB selected in, use X11 driver */
385 res = _DIBDRV_GetDisplayDriver()->pEllipse(physDev->X11PhysDev, left, top, right, bottom);
387 return res;
390 /**********************************************************************
391 * DIBDRV_ExtFloodFill
393 BOOL DIBDRV_ExtFloodFill( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color,
394 UINT fillType )
396 BOOL res;
398 MAYBE(TRACE("physDev:%p, x:%d, y:%d, color:%x, fillType:%d\n",
399 physDev, x, y, color, fillType));
401 if(physDev->hasDIB)
403 /* DIB section selected in, use DIB Engine */
404 ONCE(FIXME("STUB\n"));
405 res = TRUE;
407 else
409 /* DDB selected in, use X11 driver */
410 res = _DIBDRV_GetDisplayDriver()->pExtFloodFill(physDev->X11PhysDev, x, y, color, fillType);
412 return res;
415 /***********************************************************************
416 * DIBDRV_GetDCOrgEx
418 BOOL DIBDRV_GetDCOrgEx( DIBDRVPHYSDEV *physDev, LPPOINT lpp )
420 BOOL res;
422 MAYBE(TRACE("physDev:%p, lpp:%p\n", physDev, lpp));
424 if(physDev->hasDIB)
426 /* DIB section selected in, use DIB Engine */
427 ONCE(FIXME("STUB\n"));
428 res = TRUE;
430 else
432 /* DDB selected in, use X11 driver */
433 res = _DIBDRV_GetDisplayDriver()->pGetDCOrgEx(physDev->X11PhysDev, lpp);
435 return res;
438 /***********************************************************************
439 * DIBDRV_GetPixel
441 COLORREF DIBDRV_GetPixel( DIBDRVPHYSDEV *physDev, int x, int y )
443 COLORREF res;
445 MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
447 if(physDev->hasDIB)
449 res = physDev->physBitmap.funcs->GetPixel(&physDev->physBitmap, x, y);
451 else
453 /* DDB selected in, use X11 driver */
454 res = _DIBDRV_GetDisplayDriver()->pGetPixel(physDev->X11PhysDev, x, y);
456 return res;
459 /***********************************************************************
460 * DIBDRV_LineTo
462 BOOL DIBDRV_LineTo( DIBDRVPHYSDEV *physDev, int x, int y )
464 BOOL res;
465 POINT curPos;
467 MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
469 if(physDev->hasDIB)
471 GetCurrentPositionEx(physDev->hdc, &curPos);
473 _DIBDRV_ResetDashOrigin(physDev);
475 if(curPos.y == y)
476 physDev->penHLine(physDev, curPos.x, x, y);
477 else if(curPos.x == x)
478 physDev->penVLine(physDev, x, curPos.y, y);
479 else
480 physDev->penLine(physDev, curPos.x, curPos.y, x, y);
481 res = TRUE;
483 else
485 /* DDB selected in, use X11 driver */
486 res = _DIBDRV_GetDisplayDriver()->pLineTo(physDev->X11PhysDev, x, y);
488 return res;
491 /***********************************************************************
492 * DIBDRV_PaintRgn
494 BOOL DIBDRV_Rectangle( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom);
495 BOOL DIBDRV_PaintRgn( DIBDRVPHYSDEV *physDev, HRGN hrgn )
497 BOOL res = FALSE;
498 int i;
499 RECT *rect;
500 RGNDATA *data;
501 int size;
503 MAYBE(TRACE("physDev:%p, hrgn:%p\n", physDev, hrgn));
505 if(physDev->hasDIB)
507 /* gets needed region data size */
508 if(!(size = GetRegionData(hrgn, 0, NULL)))
509 goto fin;
511 /* allocates buffer and gets actual region data */
512 if(!(data = HeapAlloc(GetProcessHeap(), 0, size)))
513 goto fin;
514 if(!GetRegionData(hrgn, size, data))
516 HeapFree(GetProcessHeap(), 0, data);
517 goto fin;
520 /* paints the filled rectangles */
521 rect = (RECT *)data->Buffer;
522 for(i = 0; i < data->rdh.nCount; i++)
524 DIBDRV_Rectangle( physDev, rect->left, rect->top, rect->right, rect->bottom);
525 rect++;
527 HeapFree( GetProcessHeap(), 0, data );
528 res = TRUE;
529 fin:
532 else
534 /* DDB selected in, use X11 driver */
535 res = _DIBDRV_GetDisplayDriver()->pPaintRgn(physDev->X11PhysDev, hrgn);
537 return res;
540 /***********************************************************************
541 * DIBDRV_Pie
543 BOOL DIBDRV_Pie( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
544 int xstart, int ystart, int xend, int yend )
546 BOOL res;
548 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
549 physDev, left, top, right, bottom, xstart, ystart, xend, yend));
551 if(physDev->hasDIB)
553 /* DIB section selected in, use DIB Engine */
554 ONCE(FIXME("STUB\n"));
555 res = TRUE;
557 else
559 /* DDB selected in, use X11 driver */
560 res = _DIBDRV_GetDisplayDriver()->pPie(physDev->X11PhysDev, left, top, right, bottom,
561 xstart, ystart, xend, yend);
563 return res;
566 /**********************************************************************
567 * DIBDRV_Polygon
569 BOOL DIBDRV_Polygon( DIBDRVPHYSDEV *physDev, const POINT* ptw, int count )
571 BOOL res;
572 POINT *pt;
573 RECT *r;
574 int iRec;
575 POINT *clipped;
576 int clippedCount;
577 RECT bBox;
578 int ys;
579 POINT *scans;
580 int scanCount, iScan;
581 const POINT *p1, *p2;
582 int iPoint;
583 POINT pc1, pc2;
585 MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, ptw, count));
587 if(physDev->hasDIB)
589 /* DIB section selected in, use DIB Engine */
591 res = FALSE;
593 /* first converts all points to device coords */
594 if(!(pt = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT) * count)))
595 goto fin;
596 memcpy(pt, ptw, sizeof(POINT) * count);
597 LPtoDP(physDev->hdc, pt, count);
599 /* cycle on all current clipping rectangles */
600 r = physDev->regionRects;
601 for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++)
603 /* filled area */
604 if(ClipPolygon(pt, count, r, &clipped, &clippedCount))
606 /* gets polygon bounding box -- for ytop and ybottom */
607 PolygonBoundingBox(clipped, clippedCount, &bBox);
609 /* gets all ordered intersections of polygon with
610 current scanline */
611 for(ys = bBox.top; ys < bBox.bottom; ys++)
613 if(ScanPolygon(clipped, clippedCount, ys, &scans, &scanCount))
615 if(scanCount >= 2)
617 res = TRUE;
618 p1 = scans;
619 p2 = p1+1;
620 iScan = 0;
621 while(iScan < scanCount - 1)
623 physDev->brushHLine(physDev, p1->x, p2->x, ys);
624 p1 +=2;
625 p2 +=2;
626 iScan +=2;
629 HeapFree(GetProcessHeap(), 0, scans);
632 HeapFree(GetProcessHeap(), 0, clipped);
635 /* perimeter -- don't use PolyLine for speed */
636 p2 = pt;
637 for(iPoint = 0; iPoint < count -1; iPoint++)
639 p1 = p2++;
640 if(ClipLine(p1, p2, r, &pc1, &pc2))
642 res = TRUE;
643 physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
646 p1 = p2;
647 p2 = pt;
648 if(ClipLine(p1, p2, r, &pc1, &pc2))
650 res = TRUE;
651 physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
655 HeapFree(GetProcessHeap(), 0, pt);
658 else
660 /* DDB selected in, use X11 driver */
661 res = _DIBDRV_GetDisplayDriver()->pPolygon(physDev->X11PhysDev, ptw, count);
663 fin:
664 return res;
667 /**********************************************************************
668 * DIBDRV_Polyline
670 BOOL DIBDRV_Polyline( DIBDRVPHYSDEV *physDev, const POINT* ptw, int count )
672 BOOL res;
674 MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, ptw, count));
676 if(physDev->hasDIB)
678 /* DIB section selected in, use DIB Engine */
679 POINT *pt;
680 RECT *r;
681 POINT pc1, pc2;
682 int iRec, iPoint;
684 if(count < 2)
685 return FALSE;
686 res = FALSE;
688 /* first converts all points to device coords */
689 if(!(pt = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT) * count)))
690 return FALSE;
691 memcpy(pt, ptw, sizeof(POINT) * count);
692 LPtoDP(physDev->hdc, pt, count);
694 r = physDev->regionRects;
695 for(iRec = 0; iRec < physDev->regionRectCount; iRec++)
697 const POINT *p2 = pt, *p1;
698 for(iPoint = 0; iPoint < count -1; iPoint++)
700 p1 = p2++;
701 if(ClipLine(p1, p2, r, &pc1, &pc2))
703 res = TRUE;
704 physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
707 r++;
710 HeapFree(GetProcessHeap(), 0, pt);
712 return res;
714 else
716 /* DDB selected in, use X11 driver */
717 res = _DIBDRV_GetDisplayDriver()->pPolyline(physDev->X11PhysDev, ptw, count);
719 return res;
722 /**********************************************************************
723 * DIBDRV_PolyPolygon
725 BOOL DIBDRV_PolyPolygon( DIBDRVPHYSDEV *physDev, const POINT* pt, const int* counts, UINT polygons)
727 BOOL res;
729 MAYBE(TRACE("physDev:%p, pt:%p, counts:%p, polygons:%d\n", physDev, pt, counts, polygons));
731 if(physDev->hasDIB)
733 /* DIB section selected in, use DIB Engine */
734 ONCE(FIXME("STUB\n"));
735 res = TRUE;
737 else
739 /* DDB selected in, use X11 driver */
740 res = _DIBDRV_GetDisplayDriver()->pPolyPolygon(physDev->X11PhysDev, pt, counts, polygons);
742 return res;
745 /**********************************************************************
746 * DIBDRV_PolyPolyline
748 BOOL DIBDRV_PolyPolyline( DIBDRVPHYSDEV *physDev, const POINT* pt, const DWORD* counts,
749 DWORD polylines )
751 BOOL res;
753 MAYBE(TRACE("physDev:%p, pt:%p, counts:%p, polylines:%d\n", physDev, pt, counts, polylines));
755 if(physDev->hasDIB)
757 /* DIB section selected in, use DIB Engine */
758 ONCE(FIXME("STUB\n"));
759 res = TRUE;
761 else
763 /* DDB selected in, use X11 driver */
764 res = _DIBDRV_GetDisplayDriver()->pPolyPolyline(physDev->X11PhysDev, pt, counts, polylines);
766 return res;
769 /***********************************************************************
770 * DIBDRV_Rectangle
772 BOOL DIBDRV_Rectangle( DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2)
774 BOOL res = TRUE;
775 int i;
776 DIBDRVBITMAP *bmp = &physDev->physBitmap;
778 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d\n", physDev, x1, y1, x2, y2));
780 if(physDev->hasDIB)
782 OrderInt(&x1, &x2);
783 OrderInt(&y1, &y2);
785 /* temporary fix.... should be done by clipping */
786 if(x1 < 0) x1 = 0;
787 if(x2 < 0) x2 = 0;
788 if(y1 < 0) y1 = 0;
789 if(y2 < 0) y2 = 0;
790 if(x1 >= bmp->width) x1 = bmp->width - 1;
791 if(y1 >= bmp->height) y1 = bmp->height - 1;
792 if(x2 > bmp->width) x2 = bmp->width;
793 if(y2 > bmp->height) y2 = bmp->height ;
794 if(x1 >= x2 || y1 >= y2)
795 goto fin;
797 _DIBDRV_ResetDashOrigin(physDev);
799 /* particular case where the rectangle
800 degenerates to a line or a point */
801 if(x1 >= x2 - 1)
803 physDev->penVLine(physDev, x1, y1, y2);
804 goto fin;
806 else if (y1 >= y2 -1)
808 physDev->penHLine(physDev, x1, x2, y1);
809 goto fin;
812 /* Draw the perimeter */
813 physDev->penHLine(physDev, x1 , x2 , y1 );
814 physDev->penHLine(physDev, x1 , x2 , y2 - 1);
815 physDev->penVLine(physDev, x1 , y1 + 1, y2 - 1);
816 physDev->penVLine(physDev, x2 - 1, y1 + 1, y2 - 1);
818 /* fill the inside */
819 if(x2 >= x1 + 2)
820 for (i = y1 + 1; i < y2 - 1; i++)
821 physDev->brushHLine(physDev, x1 + 1, x2 - 1, i);
823 res = TRUE;
824 fin:
827 else
829 /* DDB selected in, use X11 driver */
830 res = _DIBDRV_GetDisplayDriver()->pRectangle(physDev->X11PhysDev, x1, y1, x2, y2);
832 return res;
835 /***********************************************************************
836 * DIBDRV_RoundRect
838 BOOL DIBDRV_RoundRect( DIBDRVPHYSDEV *physDev, int left, int top, int right,
839 int bottom, int ell_width, int ell_height )
841 BOOL res;
843 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, ell_width:%d, ell_height:%d\n",
844 physDev, left, top, right, bottom, ell_width, ell_height));
846 if(physDev->hasDIB)
848 /* DIB section selected in, use DIB Engine */
849 ONCE(FIXME("STUB\n"));
850 res = TRUE;
852 else
854 /* DDB selected in, use X11 driver */
855 res = _DIBDRV_GetDisplayDriver()->pRoundRect(physDev->X11PhysDev, left, top, right, bottom,
856 ell_width, ell_height);
858 return res;
861 /***********************************************************************
862 * DIBDRV_SetPixel
864 COLORREF DIBDRV_SetPixel( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color )
866 COLORREF res;
867 DWORD and, xor;
869 MAYBE(TRACE("physDev:%p, x:%d, y:%d, color:%x\n", physDev, x, y, color));
871 if(physDev->hasDIB)
873 /* gets previous pixel */
874 res = physDev->physBitmap.funcs->GetPixel(&physDev->physBitmap, x, y);
876 /* calculates AND and XOR from color */
877 _DIBDRV_CalcAndXorMasks(GetROP2(physDev->hdc), color, &and, &xor);
879 /* sets the pixel */
880 physDev->physBitmap.funcs->SetPixel(&physDev->physBitmap, x, y, and, xor);
882 else
884 /* DDB selected in, use X11 driver */
885 res = _DIBDRV_GetDisplayDriver()->pSetPixel(physDev->X11PhysDev, x, y, color);
887 return res;
890 /***********************************************************************
891 * DIBDRV_SetDCOrg
893 DWORD DIBDRV_SetDCOrg( DIBDRVPHYSDEV *physDev, int x, int y )
895 DWORD res;
897 MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
899 if(physDev->hasDIB)
901 /* DIB section selected in, use DIB Engine */
902 ONCE(FIXME("STUB\n"));
903 res = 0;
905 else
907 /* DDB selected in, use X11 driver */
908 res = _DIBDRV_GetDisplayDriver()->pSetDCOrg(physDev->X11PhysDev, x, y);
910 return res;