2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Line functions
5 * FILE: win32ss/gdi/eng/lineto.c
6 * PROGRAMER: ReactOS Team
15 TranslateRects(RECT_ENUM
*RectEnum
, POINTL
* Translate
)
19 if (0 != Translate
->x
|| 0 != Translate
->y
)
21 for (CurrentRect
= RectEnum
->arcl
; CurrentRect
< RectEnum
->arcl
+ RectEnum
->c
; CurrentRect
++)
23 CurrentRect
->left
+= Translate
->x
;
24 CurrentRect
->right
+= Translate
->x
;
25 CurrentRect
->top
+= Translate
->y
;
26 CurrentRect
->bottom
+= Translate
->y
;
43 PEBRUSHOBJ pebo
= (PEBRUSHOBJ
)pbo
;
44 PULONG pulStyles
= pebo
->pbrush
->pStyle
;
45 ULONG iStyle
, cStyles
= pebo
->pbrush
->dwStyleCount
;
46 LONG diStyle
, offStyle
, lStyleMax
;
52 offStyle
= (- Translate
->x
) % pebo
->pbrush
->ulStyleSize
;
58 offStyle
= (- Translate
->y
) % pebo
->pbrush
->ulStyleSize
;
63 /* Now loop until we have found the style index */
64 for (iStyle
= 0; offStyle
>= pulStyles
[iStyle
]; iStyle
++)
66 offStyle
-= pulStyles
[iStyle
];
71 lStyleMax
+= pulStyles
[iStyle
] - offStyle
;
75 lStyleMax
-= offStyle
+ 1;
81 lStyleMax
= MAX_COORD
;
89 * Draw a line from top-left to bottom-right
92 NWtoSE(SURFOBJ
* OutputObj
, CLIPOBJ
* Clip
,
93 BRUSHOBJ
* pbo
, LONG x
, LONG y
, LONG deltax
, LONG deltay
,
101 ULONG Pixel
= pbo
->iSolidColor
;
103 PEBRUSHOBJ pebo
= (PEBRUSHOBJ
)pbo
;
104 PULONG pulStyles
= pebo
->pbrush
->pStyle
;
105 ULONG iStyle
, cStyles
= pebo
->pbrush
->dwStyleCount
;
108 lStyleMax
= HandleStyles(pbo
, Translate
, x
, y
, deltax
, deltay
, 1, 1, &iStyle
);
110 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_RIGHTDOWN
, 0);
111 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
112 TranslateRects(&RectEnum
, Translate
);
113 ClipRect
= RectEnum
.arcl
;
114 delta
= max(deltax
, deltay
);
117 while (i
< delta
&& (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
|| EnumMore
))
119 while ((ClipRect
< RectEnum
.arcl
+ RectEnum
.c
/* there's still a current clip rect */
120 && (ClipRect
->bottom
<= y
/* but it's above us */
121 || (ClipRect
->top
<= y
&& ClipRect
->right
<= x
))) /* or to the left of us */
122 || EnumMore
) /* no current clip rect, but rects left */
124 /* Skip to the next clip rect */
125 if (RectEnum
.arcl
+ RectEnum
.c
<= ClipRect
)
127 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
128 TranslateRects(&RectEnum
, Translate
);
129 ClipRect
= RectEnum
.arcl
;
136 if (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
) /* If there's no current clip rect we're done */
138 if ((ClipRect
->left
<= x
&& ClipRect
->top
<= y
) && ((iStyle
& 1) == 0))
140 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_PutPixel(
141 OutputObj
, x
, y
, Pixel
);
148 iStyle
= (iStyle
+ 1) % cStyles
;
149 lStyleMax
= y
+ pulStyles
[iStyle
];
151 error
= error
+ deltax
;
155 error
= error
- deltay
;
163 iStyle
= (iStyle
+ 1) % cStyles
;
164 lStyleMax
= x
+ pulStyles
[iStyle
];
166 error
= error
+ deltay
;
170 error
= error
- deltax
;
179 SWtoNE(SURFOBJ
* OutputObj
, CLIPOBJ
* Clip
,
180 BRUSHOBJ
* pbo
, LONG x
, LONG y
, LONG deltax
, LONG deltay
,
188 ULONG Pixel
= pbo
->iSolidColor
;
190 PEBRUSHOBJ pebo
= (PEBRUSHOBJ
)pbo
;
191 PULONG pulStyles
= pebo
->pbrush
->pStyle
;
192 ULONG iStyle
, cStyles
= pebo
->pbrush
->dwStyleCount
;
195 lStyleMax
= HandleStyles(pbo
, Translate
, x
, y
, deltax
, deltay
, 1, -1, &iStyle
);
197 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_RIGHTUP
, 0);
198 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
199 TranslateRects(&RectEnum
, Translate
);
200 ClipRect
= RectEnum
.arcl
;
201 delta
= max(deltax
, deltay
);
204 while (i
< delta
&& (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
|| EnumMore
))
206 while ((ClipRect
< RectEnum
.arcl
+ RectEnum
.c
207 && (y
< ClipRect
->top
208 || (y
< ClipRect
->bottom
&& ClipRect
->right
<= x
)))
211 if (RectEnum
.arcl
+ RectEnum
.c
<= ClipRect
)
213 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
214 TranslateRects(&RectEnum
, Translate
);
215 ClipRect
= RectEnum
.arcl
;
222 if (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
)
224 if ((ClipRect
->left
<= x
&& y
< ClipRect
->bottom
) && ((iStyle
& 1) == 0))
226 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_PutPixel(
227 OutputObj
, x
, y
, Pixel
);
234 iStyle
= (iStyle
- 1) % cStyles
;
235 lStyleMax
= y
- pulStyles
[iStyle
];
237 error
= error
+ deltax
;
241 error
= error
- deltay
;
249 iStyle
= (iStyle
+ 1) % cStyles
;
250 lStyleMax
= x
+ pulStyles
[iStyle
];
252 error
= error
+ deltay
;
256 error
= error
- deltax
;
265 NEtoSW(SURFOBJ
* OutputObj
, CLIPOBJ
* Clip
,
266 BRUSHOBJ
* pbo
, LONG x
, LONG y
, LONG deltax
, LONG deltay
,
274 ULONG Pixel
= pbo
->iSolidColor
;
276 PEBRUSHOBJ pebo
= (PEBRUSHOBJ
)pbo
;
277 PULONG pulStyles
= pebo
->pbrush
->pStyle
;
278 ULONG iStyle
, cStyles
= pebo
->pbrush
->dwStyleCount
;
281 lStyleMax
= HandleStyles(pbo
, Translate
, x
, y
, deltax
, deltay
, -1, 1, &iStyle
);
283 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_LEFTDOWN
, 0);
284 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
285 TranslateRects(&RectEnum
, Translate
);
286 ClipRect
= RectEnum
.arcl
;
287 delta
= max(deltax
, deltay
);
290 while (i
< delta
&& (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
|| EnumMore
))
292 while ((ClipRect
< RectEnum
.arcl
+ RectEnum
.c
293 && (ClipRect
->bottom
<= y
294 || (ClipRect
->top
<= y
&& x
< ClipRect
->left
)))
297 if (RectEnum
.arcl
+ RectEnum
.c
<= ClipRect
)
299 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
300 TranslateRects(&RectEnum
, Translate
);
301 ClipRect
= RectEnum
.arcl
;
308 if (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
)
310 if ((x
< ClipRect
->right
&& ClipRect
->top
<= y
) && ((iStyle
& 1) == 0))
312 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_PutPixel(
313 OutputObj
, x
, y
, Pixel
);
320 iStyle
= (iStyle
+ 1) % cStyles
;
321 lStyleMax
= y
+ pulStyles
[iStyle
];
323 error
= error
+ deltax
;
327 error
= error
- deltay
;
335 iStyle
= (iStyle
- 1) % cStyles
;
336 lStyleMax
= x
- pulStyles
[iStyle
];
338 error
= error
+ deltay
;
342 error
= error
- deltax
;
351 SEtoNW(SURFOBJ
* OutputObj
, CLIPOBJ
* Clip
,
352 BRUSHOBJ
* pbo
, LONG x
, LONG y
, LONG deltax
, LONG deltay
,
360 ULONG Pixel
= pbo
->iSolidColor
;
362 PEBRUSHOBJ pebo
= (PEBRUSHOBJ
)pbo
;
363 PULONG pulStyles
= pebo
->pbrush
->pStyle
;
364 ULONG iStyle
, cStyles
= pebo
->pbrush
->dwStyleCount
;
367 lStyleMax
= HandleStyles(pbo
, Translate
, x
, y
, deltax
, deltay
, -1, -1, &iStyle
);
369 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_LEFTUP
, 0);
370 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
371 TranslateRects(&RectEnum
, Translate
);
372 ClipRect
= RectEnum
.arcl
;
373 delta
= max(deltax
, deltay
);
376 while (i
< delta
&& (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
|| EnumMore
))
378 while ((ClipRect
< RectEnum
.arcl
+ RectEnum
.c
379 && (y
< ClipRect
->top
380 || (y
< ClipRect
->bottom
&& x
< ClipRect
->left
)))
383 if (RectEnum
.arcl
+ RectEnum
.c
<= ClipRect
)
385 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
386 TranslateRects(&RectEnum
, Translate
);
387 ClipRect
= RectEnum
.arcl
;
394 if (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
)
396 if ((x
< ClipRect
->right
&& y
< ClipRect
->bottom
) && ((iStyle
& 1) == 0))
398 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_PutPixel(
399 OutputObj
, x
, y
, Pixel
);
406 iStyle
= (iStyle
- 1) % cStyles
;
407 lStyleMax
= y
- pulStyles
[iStyle
];
409 error
= error
+ deltax
;
413 error
= error
- deltay
;
421 iStyle
= (iStyle
- 1) % cStyles
;
422 lStyleMax
= x
- pulStyles
[iStyle
];
424 error
= error
+ deltay
;
428 error
= error
- deltax
;
441 _Inout_ SURFOBJ
*DestObj
,
448 _In_opt_ RECTL
*RectBounds
,
451 LONG x
, y
, deltax
, deltay
, xchange
, ychange
, hx
, vy
;
453 ULONG Pixel
= pbo
->iSolidColor
;
457 INTENG_ENTER_LEAVE EnterLeave
;
460 CLIPOBJ
*pcoPriv
= NULL
;
461 PEBRUSHOBJ pebo
= (PEBRUSHOBJ
)pbo
;
462 ULONG cStyles
= pebo
->pbrush
->dwStyleCount
;
472 DestRect
.right
= x1
+ 1;
477 DestRect
.bottom
= y2
;
482 DestRect
.bottom
= y1
+ 1;
485 if (! IntEngEnter(&EnterLeave
, DestObj
, &DestRect
, FALSE
, &Translate
, &OutputObj
))
492 Clip
= pcoPriv
= EngCreateClip();
497 IntEngUpdateClipRegion((XCLIPOBJ
*)Clip
, 0, 0, RectBounds
);
510 if (0 == deltax
&& 0 == deltay
)
539 if ((y1
== y2
) && (cStyles
== 0))
541 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_RIGHTDOWN
, 0);
544 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
545 for (i
= 0; i
< RectEnum
.c
&& RectEnum
.arcl
[i
].top
+ Translate
.y
<= y1
; i
++)
547 if (y1
< RectEnum
.arcl
[i
].bottom
+ Translate
.y
&&
548 RectEnum
.arcl
[i
].left
+ Translate
.x
<= hx
+ deltax
&&
549 hx
< RectEnum
.arcl
[i
].right
+ Translate
.x
&&
550 max(hx
, RectEnum
.arcl
[i
].left
+ Translate
.x
) <
551 min(hx
+ deltax
, RectEnum
.arcl
[i
].right
+ Translate
.x
))
553 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_HLine(
555 max(hx
, RectEnum
.arcl
[i
].left
+ Translate
.x
),
556 min(hx
+ deltax
, RectEnum
.arcl
[i
].right
+ Translate
.x
),
563 else if ((x1
== x2
) && (cStyles
== 0))
565 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_RIGHTDOWN
, 0);
568 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
569 for (i
= 0; i
< RectEnum
.c
; i
++)
571 if (RectEnum
.arcl
[i
].left
+ Translate
.x
<= x1
&&
572 x1
< RectEnum
.arcl
[i
].right
+ Translate
.x
&&
573 RectEnum
.arcl
[i
].top
+ Translate
.y
<= vy
+ deltay
&&
574 vy
< RectEnum
.arcl
[i
].bottom
+ Translate
.y
)
576 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_VLine(
578 max(vy
, RectEnum
.arcl
[i
].top
+ Translate
.y
),
579 min(vy
+ deltay
, RectEnum
.arcl
[i
].bottom
+ Translate
.y
),
592 NWtoSE(OutputObj
, Clip
, pbo
, x
, y
, deltax
, deltay
, &Translate
);
596 SWtoNE(OutputObj
, Clip
, pbo
, x
, y
, deltax
, deltay
, &Translate
);
603 NEtoSW(OutputObj
, Clip
, pbo
, x
, y
, deltax
, deltay
, &Translate
);
607 SEtoNW(OutputObj
, Clip
, pbo
, x
, y
, deltax
, deltay
, &Translate
);
614 EngDeleteClip(pcoPriv
);
617 return IntEngLeave(&EnterLeave
);
621 IntEngLineTo(SURFOBJ
*psoDest
,
637 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
640 GdiBrush
= CONTAINING_RECORD(
645 ASSERT(GdiBrush
->pbrush
);
647 if (GdiBrush
->pbrush
->flAttrs
& BR_IS_NULL
)
653 /* Clip lines totally outside the clip region. This is not done as an
654 * optimization (there are very few lines drawn outside the region) but
655 * as a workaround for what seems to be a problem in the CL54XX driver */
656 if (NULL
== ClipObj
|| DC_TRIVIAL
== ClipObj
->iDComplexity
)
659 b
.right
= psoDest
->sizlBitmap
.cx
;
661 b
.bottom
= psoDest
->sizlBitmap
.cy
;
665 b
= ClipObj
->rclBounds
;
667 if ((x1
< b
.left
&& x2
< b
.left
) || (b
.right
<= x1
&& b
.right
<= x2
) ||
668 (y1
< b
.top
&& y2
< b
.top
) || (b
.bottom
<= y1
&& b
.bottom
<= y2
))
673 b
.left
= min(x1
, x2
);
674 b
.right
= max(x1
, x2
);
676 b
.bottom
= max(y1
, y2
);
677 if (b
.left
== b
.right
) b
.right
++;
678 if (b
.top
== b
.bottom
) b
.bottom
++;
680 if (psurfDest
->flags
& HOOK_LINETO
)
682 /* Call the driver's DrvLineTo */
683 ret
= GDIDEVFUNCS(psoDest
).LineTo(
684 psoDest
, ClipObj
, pbo
, x1
, y1
, x2
, y2
, &b
, Mix
);
688 if (! ret
&& (psurfDest
->flags
& HOOK_STROKEPATH
))
690 /* FIXME: Emulate LineTo using drivers DrvStrokePath and set ret on success */
696 ret
= EngLineTo(psoDest
, ClipObj
, pbo
, x1
, y1
, x2
, y2
, RectBounds
, Mix
);
703 IntEngPolyline(SURFOBJ
*psoDest
,
714 // Draw the Polyline with a call to IntEngLineTo for each segment.
715 for (i
= 1; i
< dCount
; i
++)
717 rect
.left
= min(pt
[i
-1].x
, pt
[i
].x
);
718 rect
.top
= min(pt
[i
-1].y
, pt
[i
].y
);
719 rect
.right
= max(pt
[i
-1].x
, pt
[i
].x
);
720 rect
.bottom
= max(pt
[i
-1].y
, pt
[i
].y
);
721 ret
= IntEngLineTo(psoDest
,