DIB Engine: fix MapModes for xxxBlt
[wine/hacks.git] / dlls / winedib.drv / graphics.c
blobacbda6a1ff650a470c6037cebf56620d1b681b0c
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 /* converts positions from Device space to World space */
385 void _DIBDRV_Position_ds2ws(DIBDRVPHYSDEV *physDev, int *x, int *y)
387 POINT p;
388 p.x = *x;
389 p.y = *y;
390 DPtoLP(physDev->hdc, &p, 1);
391 *x = p.x;
392 *y = p.y;
395 void _DIBDRV_Positions_ds2ws(DIBDRVPHYSDEV *physDev, int *x1, int *y1, int *x2, int *y2)
397 POINT pts[2];
398 pts[0].x = *x1;
399 pts[0].y = *y1;
400 pts[1].x = *x2;
401 pts[1].y = *y2;
402 DPtoLP(physDev->hdc, pts, 2);
403 *x1 = pts[0].x;
404 *y1 = pts[0].y;
405 *x2 = pts[1].x;
406 *y2 = pts[1].y;
409 /* converts sizes from Device space to World space */
410 void _DIBDRV_Sizes_ds2ws(DIBDRVPHYSDEV *physDev, int *w, int *h)
412 POINT pts[2];
413 pts[0].x = 0;
414 pts[0].y = 0;
415 pts[1].x = *w;
416 pts[1].y = *h;
417 DPtoLP(physDev->hdc, pts, 2);
418 *w = pts[1].x - pts[0].x;
419 *h = pts[1].y - pts[0].y;
422 /***********************************************************************
423 * DIBDRV_Arc
425 BOOL DIBDRV_Arc( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
426 int xstart, int ystart, int xend, int yend )
428 BOOL res;
430 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
431 physDev, left, top, right, bottom, xstart, ystart, xend, yend));
433 if(physDev->hasDIB)
435 /* DIB section selected in, use DIB Engine */
436 ONCE(FIXME("STUB\n"));
437 res = TRUE;
439 else
441 /* DDB selected in, use X11 driver */
442 res = _DIBDRV_GetDisplayDriver()->pArc(physDev->X11PhysDev, left, top, right, bottom,
443 xstart, ystart, xend, yend);
445 return res;
448 /***********************************************************************
449 * DIBDRV_Chord
451 BOOL DIBDRV_Chord( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
452 int xstart, int ystart, int xend, int yend )
454 BOOL res;
456 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
457 physDev, left, top, right, bottom, xstart, ystart, xend, yend));
459 if(physDev->hasDIB)
461 /* DIB section selected in, use DIB Engine */
462 ONCE(FIXME("STUB\n"));
463 res = TRUE;
465 else
467 /* DDB selected in, use X11 driver */
468 res = _DIBDRV_GetDisplayDriver()->pChord(physDev->X11PhysDev, left, top, right, bottom,
469 xstart, ystart, xend, yend);
471 return res;
474 /***********************************************************************
475 * DIBDRV_Ellipse
477 BOOL DIBDRV_Ellipse( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom )
479 BOOL res;
481 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d\n",
482 physDev, left, top, right, bottom));
484 if(physDev->hasDIB)
486 /* DIB section selected in, use DIB Engine */
487 ONCE(FIXME("STUB\n"));
488 res = TRUE;
490 else
492 /* DDB selected in, use X11 driver */
493 res = _DIBDRV_GetDisplayDriver()->pEllipse(physDev->X11PhysDev, left, top, right, bottom);
495 return res;
498 /**********************************************************************
499 * DIBDRV_ExtFloodFill
501 BOOL DIBDRV_ExtFloodFill( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color,
502 UINT fillType )
504 BOOL res;
506 MAYBE(TRACE("physDev:%p, x:%d, y:%d, color:%x, fillType:%d\n",
507 physDev, x, y, color, fillType));
509 if(physDev->hasDIB)
511 /* DIB section selected in, use DIB Engine */
512 ONCE(FIXME("STUB\n"));
513 res = TRUE;
515 else
517 /* DDB selected in, use X11 driver */
518 res = _DIBDRV_GetDisplayDriver()->pExtFloodFill(physDev->X11PhysDev, x, y, color, fillType);
520 return res;
523 /***********************************************************************
524 * DIBDRV_GetDCOrgEx
526 BOOL DIBDRV_GetDCOrgEx( DIBDRVPHYSDEV *physDev, LPPOINT lpp )
528 BOOL res;
530 MAYBE(TRACE("physDev:%p, lpp:%p\n", physDev, lpp));
532 if(physDev->hasDIB)
534 /* DIB section selected in, use DIB Engine */
535 ONCE(FIXME("STUB\n"));
536 res = TRUE;
538 else
540 /* DDB selected in, use X11 driver */
541 res = _DIBDRV_GetDisplayDriver()->pGetDCOrgEx(physDev->X11PhysDev, lpp);
543 return res;
546 /***********************************************************************
547 * DIBDRV_GetPixel
549 COLORREF DIBDRV_GetPixel( DIBDRVPHYSDEV *physDev, int x, int y )
551 COLORREF res;
553 MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
555 if(physDev->hasDIB)
557 _DIBDRV_Position_ws2ds(physDev, &x, &y);
558 res = physDev->physBitmap->funcs->GetPixel(physDev->physBitmap, x, y);
560 else
562 /* DDB selected in, use X11 driver */
563 res = _DIBDRV_GetDisplayDriver()->pGetPixel(physDev->X11PhysDev, x, y);
565 return res;
568 /***********************************************************************
569 * DIBDRV_LineTo
571 BOOL DIBDRV_LineTo( DIBDRVPHYSDEV *physDev, int x, int y )
573 BOOL res;
574 POINT curPos;
575 RECT *r;
576 int iRec;
577 POINT p1, p2, pc1, pc2;
579 MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
581 if(physDev->hasDIB)
583 res = FALSE;
584 GetCurrentPositionEx(physDev->hdc, &curPos);
586 /* converts position to device space */
587 p1.x = curPos.x; p1.y = curPos.y;
588 p2.x = x; p2.y = y;
589 LPtoDP(physDev->hdc, &p1, 1);
590 LPtoDP(physDev->hdc, &p2, 1);
592 /* cycle on all current clipping rectangles */
593 r = physDev->regionRects;
594 for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++)
596 _DIBDRV_ResetDashOrigin(physDev);
598 /* clipe line on current region area */
599 if(ClipLine(&p1, &p2, r, &pc1, &pc2))
601 if(pc1.y == pc2.y)
602 physDev->penHLine(physDev, pc1.x, pc2.x, pc1.y);
603 else if(pc1.x == pc2.x)
604 physDev->penVLine(physDev, pc1.x, pc1.y, pc2.y);
605 else
606 physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
607 res = TRUE;
611 /* moves current position to next point */
612 MoveToEx(physDev->hdc, x, y, NULL);
614 else
616 /* DDB selected in, use X11 driver */
617 res = _DIBDRV_GetDisplayDriver()->pLineTo(physDev->X11PhysDev, x, y);
619 return res;
622 /***********************************************************************
623 * DIBDRV_PaintRgn
625 BOOL DIBDRV_Rectangle( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom);
626 BOOL DIBDRV_PaintRgn( DIBDRVPHYSDEV *physDev, HRGN hrgn )
628 BOOL res = FALSE;
629 int i;
630 RECT *rect;
631 RGNDATA *data;
632 int size;
634 MAYBE(TRACE("physDev:%p, hrgn:%p\n", physDev, hrgn));
636 if(physDev->hasDIB)
638 /* gets needed region data size */
639 if(!(size = GetRegionData(hrgn, 0, NULL)))
640 goto fin;
642 /* allocates buffer and gets actual region data */
643 if(!(data = HeapAlloc(GetProcessHeap(), 0, size)))
644 goto fin;
645 if(!GetRegionData(hrgn, size, data))
647 HeapFree(GetProcessHeap(), 0, data);
648 goto fin;
651 /* paints the filled rectangles */
652 rect = (RECT *)data->Buffer;
653 for(i = 0; i < data->rdh.nCount; i++)
655 DIBDRV_Rectangle( physDev, rect->left, rect->top, rect->right, rect->bottom);
656 rect++;
658 HeapFree( GetProcessHeap(), 0, data );
659 res = TRUE;
660 fin:
663 else
665 /* DDB selected in, use X11 driver */
666 res = _DIBDRV_GetDisplayDriver()->pPaintRgn(physDev->X11PhysDev, hrgn);
668 return res;
671 /***********************************************************************
672 * DIBDRV_Pie
674 BOOL DIBDRV_Pie( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
675 int xstart, int ystart, int xend, int yend )
677 BOOL res;
679 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
680 physDev, left, top, right, bottom, xstart, ystart, xend, yend));
682 if(physDev->hasDIB)
684 /* DIB section selected in, use DIB Engine */
685 ONCE(FIXME("STUB\n"));
686 res = TRUE;
688 else
690 /* DDB selected in, use X11 driver */
691 res = _DIBDRV_GetDisplayDriver()->pPie(physDev->X11PhysDev, left, top, right, bottom,
692 xstart, ystart, xend, yend);
694 return res;
697 /**********************************************************************
698 * DIBDRV_Polygon
700 BOOL DIBDRV_Polygon( DIBDRVPHYSDEV *physDev, const POINT* ptw, int count )
702 BOOL res;
703 POINT *pt;
704 RECT *r;
705 int iRec;
706 POINT *clipped;
707 int clippedCount;
708 RECT bBox;
709 int ys;
710 POINT *scans;
711 int scanCount, iScan;
712 const POINT *p1, *p2;
713 int iPoint;
714 POINT pc1, pc2;
716 MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, ptw, count));
718 if(physDev->hasDIB)
720 /* DIB section selected in, use DIB Engine */
722 res = FALSE;
724 /* first converts all points to device coords */
725 if(!(pt = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT) * count)))
726 goto fin;
727 memcpy(pt, ptw, sizeof(POINT) * count);
728 LPtoDP(physDev->hdc, pt, count);
730 /* cycle on all current clipping rectangles */
731 r = physDev->regionRects;
732 for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++)
734 /* filled area */
735 if(ClipPolygon(pt, count, r, &clipped, &clippedCount))
737 /* gets polygon bounding box -- for ytop and ybottom */
738 PolygonBoundingBox(clipped, clippedCount, &bBox);
740 /* gets all ordered intersections of polygon with
741 current scanline */
742 for(ys = bBox.top; ys < bBox.bottom; ys++)
744 if(ScanPolygon(clipped, clippedCount, ys, &scans, &scanCount))
746 if(scanCount >= 2)
748 res = TRUE;
749 p1 = scans;
750 p2 = p1+1;
751 iScan = 0;
752 while(iScan < scanCount - 1)
754 physDev->brushHLine(physDev, p1->x, p2->x, ys);
755 p1 +=2;
756 p2 +=2;
757 iScan +=2;
760 HeapFree(GetProcessHeap(), 0, scans);
763 HeapFree(GetProcessHeap(), 0, clipped);
766 /* perimeter -- don't use PolyLine for speed */
767 p2 = pt;
768 for(iPoint = 0; iPoint < count -1; iPoint++)
770 p1 = p2++;
771 if(ClipLine(p1, p2, r, &pc1, &pc2))
773 res = TRUE;
774 physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
777 p1 = p2;
778 p2 = pt;
779 if(ClipLine(p1, p2, r, &pc1, &pc2))
781 res = TRUE;
782 physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
786 HeapFree(GetProcessHeap(), 0, pt);
789 else
791 /* DDB selected in, use X11 driver */
792 res = _DIBDRV_GetDisplayDriver()->pPolygon(physDev->X11PhysDev, ptw, count);
794 fin:
795 return res;
798 /**********************************************************************
799 * DIBDRV_Polyline
801 BOOL DIBDRV_Polyline( DIBDRVPHYSDEV *physDev, const POINT* ptw, int count )
803 BOOL res;
805 MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, ptw, count));
807 if(physDev->hasDIB)
809 /* DIB section selected in, use DIB Engine */
810 POINT *pt;
811 RECT *r;
812 POINT pc1, pc2;
813 int iRec, iPoint;
815 if(count < 2)
816 return FALSE;
817 res = FALSE;
819 /* first converts all points to device coords */
820 if(!(pt = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT) * count)))
821 return FALSE;
822 memcpy(pt, ptw, sizeof(POINT) * count);
823 LPtoDP(physDev->hdc, pt, count);
825 r = physDev->regionRects;
826 for(iRec = 0; iRec < physDev->regionRectCount; iRec++)
828 const POINT *p2 = pt, *p1;
829 for(iPoint = 0; iPoint < count -1; iPoint++)
831 p1 = p2++;
832 if(ClipLine(p1, p2, r, &pc1, &pc2))
834 res = TRUE;
835 physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
838 r++;
841 HeapFree(GetProcessHeap(), 0, pt);
843 return res;
845 else
847 /* DDB selected in, use X11 driver */
848 res = _DIBDRV_GetDisplayDriver()->pPolyline(physDev->X11PhysDev, ptw, count);
850 return res;
853 /**********************************************************************
854 * DIBDRV_PolyPolygon
856 BOOL DIBDRV_PolyPolygon( DIBDRVPHYSDEV *physDev, const POINT* pt, const int* counts, UINT polygons)
858 BOOL res;
860 MAYBE(TRACE("physDev:%p, pt:%p, counts:%p, polygons:%d\n", physDev, pt, counts, polygons));
862 if(physDev->hasDIB)
864 /* DIB section selected in, use DIB Engine */
865 ONCE(FIXME("STUB\n"));
866 res = TRUE;
868 else
870 /* DDB selected in, use X11 driver */
871 res = _DIBDRV_GetDisplayDriver()->pPolyPolygon(physDev->X11PhysDev, pt, counts, polygons);
873 return res;
876 /**********************************************************************
877 * DIBDRV_PolyPolyline
879 BOOL DIBDRV_PolyPolyline( DIBDRVPHYSDEV *physDev, const POINT* pt, const DWORD* counts,
880 DWORD polylines )
882 BOOL res;
884 MAYBE(TRACE("physDev:%p, pt:%p, counts:%p, polylines:%d\n", physDev, pt, counts, polylines));
886 if(physDev->hasDIB)
888 /* DIB section selected in, use DIB Engine */
889 ONCE(FIXME("STUB\n"));
890 res = TRUE;
892 else
894 /* DDB selected in, use X11 driver */
895 res = _DIBDRV_GetDisplayDriver()->pPolyPolyline(physDev->X11PhysDev, pt, counts, polylines);
897 return res;
900 /***********************************************************************
901 * DIBDRV_Rectangle
903 BOOL DIBDRV_Rectangle( DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2)
905 BOOL res;
906 int i;
907 RECT rWorld, rDevice, rClipped;
908 RECT *r;
909 int iRec;
911 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d\n", physDev, x1, y1, x2, y2));
913 if(physDev->hasDIB)
915 res = FALSE;
917 OrderInt(&x1, &x2);
918 OrderInt(&y1, &y2);
920 /* converts to device space */
921 rWorld.left = x1; rWorld.top = y1; rWorld.right = x2; rWorld.bottom = y2;
922 _DIBDRV_Rect_ws2ds(physDev, &rWorld, &rDevice);
924 /* loop on all clip region rectangles */
925 r = physDev->regionRects;
926 for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++)
928 /* clips rectangle to current region */
929 if(_DIBDRV_IntersectRect(&rClipped, &rDevice, r))
931 x1 = rClipped.left; y1 = rClipped.top;
932 x2 = rClipped.right; y2 = rClipped.bottom;
934 _DIBDRV_ResetDashOrigin(physDev);
936 /* fill the inside, if not null brush */
937 if(physDev->brushStyle != BS_NULL)
939 if(x2 > x1)
940 for (i = y1; i < y2; i++)
941 physDev->brushHLine(physDev, x1, x2, i);
944 /* draw perimeter, if not null pen */
945 if(physDev->penStyle != PS_NULL)
948 /* particular case where the rectangle
949 degenerates to a line or a point */
950 if(x1 >= x2 - 1)
951 physDev->penVLine(physDev, x1, y1, y2);
952 else if (y1 >= y2 -1)
953 physDev->penHLine(physDev, x1, x2, y1);
954 else
956 /* Draw the perimeter */
957 physDev->penHLine(physDev, x1 , x2 , y1 );
958 physDev->penHLine(physDev, x1 , x2 , y2 - 1);
959 physDev->penVLine(physDev, x1 , y1 + 1, y2 - 1);
960 physDev->penVLine(physDev, x2 - 1, y1 + 1, y2 - 1);
963 res = TRUE;
967 else
969 /* DDB selected in, use X11 driver */
970 res = _DIBDRV_GetDisplayDriver()->pRectangle(physDev->X11PhysDev, x1, y1, x2, y2);
972 return res;
975 /***********************************************************************
976 * DIBDRV_RoundRect
978 BOOL DIBDRV_RoundRect( DIBDRVPHYSDEV *physDev, int left, int top, int right,
979 int bottom, int ell_width, int ell_height )
981 BOOL res;
983 MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, ell_width:%d, ell_height:%d\n",
984 physDev, left, top, right, bottom, ell_width, ell_height));
986 if(physDev->hasDIB)
988 /* DIB section selected in, use DIB Engine */
989 ONCE(FIXME("STUB\n"));
990 res = TRUE;
992 else
994 /* DDB selected in, use X11 driver */
995 res = _DIBDRV_GetDisplayDriver()->pRoundRect(physDev->X11PhysDev, left, top, right, bottom,
996 ell_width, ell_height);
998 return res;
1001 /***********************************************************************
1002 * DIBDRV_SetPixel
1004 COLORREF DIBDRV_SetPixel( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color )
1006 COLORREF res;
1007 DWORD and, xor;
1009 MAYBE(TRACE("physDev:%p, x:%d, y:%d, color:%x\n", physDev, x, y, color));
1011 if(physDev->hasDIB)
1013 /* get real colorref */
1014 color = _DIBDRV_MapColor(physDev, color);
1016 /* map to pixel color / palette index */
1017 color = physDev->physBitmap->funcs->ColorToPixel(physDev->physBitmap, color);
1019 _DIBDRV_Position_ws2ds(physDev, &x, &y);
1021 /* gets previous pixel */
1022 res = physDev->physBitmap->funcs->GetPixel(physDev->physBitmap, x, y);
1024 /* calculates AND and XOR from color */
1025 _DIBDRV_CalcAndXorMasks(GetROP2(physDev->hdc), color, &and, &xor);
1027 /* sets the pixel */
1028 physDev->physBitmap->funcs->SetPixel(physDev->physBitmap, x, y, and, xor);
1030 else
1032 /* DDB selected in, use X11 driver */
1033 res = _DIBDRV_GetDisplayDriver()->pSetPixel(physDev->X11PhysDev, x, y, color);
1035 return res;
1038 /***********************************************************************
1039 * DIBDRV_SetDCOrg
1041 DWORD DIBDRV_SetDCOrg( DIBDRVPHYSDEV *physDev, int x, int y )
1043 DWORD res;
1045 MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
1047 if(physDev->hasDIB)
1049 /* DIB section selected in, use DIB Engine */
1050 ONCE(FIXME("STUB\n"));
1051 res = 0;
1053 else
1055 /* DDB selected in, use X11 driver */
1056 res = _DIBDRV_GetDisplayDriver()->pSetDCOrg(physDev->X11PhysDev, x, y);
1058 return res;