2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Line functions
5 * FILE: subsystems/win32/win32k/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
;
32 * Draw a line from top-left to bottom-right
35 NWtoSE(SURFOBJ
* OutputObj
, CLIPOBJ
* Clip
,
36 BRUSHOBJ
* pbo
, LONG x
, LONG y
, LONG deltax
, LONG deltay
,
44 ULONG Pixel
= pbo
->iSolidColor
;
47 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_RIGHTDOWN
, 0);
48 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
49 TranslateRects(&RectEnum
, Translate
);
50 ClipRect
= RectEnum
.arcl
;
51 delta
= max(deltax
, deltay
);
54 while (i
< delta
&& (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
|| EnumMore
))
56 while ((ClipRect
< RectEnum
.arcl
+ RectEnum
.c
/* there's still a current clip rect */
57 && (ClipRect
->bottom
<= y
/* but it's above us */
58 || (ClipRect
->top
<= y
&& ClipRect
->right
<= x
))) /* or to the left of us */
59 || EnumMore
) /* no current clip rect, but rects left */
61 /* Skip to the next clip rect */
62 if (RectEnum
.arcl
+ RectEnum
.c
<= ClipRect
)
64 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
65 TranslateRects(&RectEnum
, Translate
);
66 ClipRect
= RectEnum
.arcl
;
73 if (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
) /* If there's no current clip rect we're done */
75 if (ClipRect
->left
<= x
&& ClipRect
->top
<= y
)
77 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_PutPixel(
78 OutputObj
, x
, y
, Pixel
);
83 error
= error
+ deltax
;
87 error
= error
- deltay
;
93 error
= error
+ deltay
;
97 error
= error
- deltax
;
106 SWtoNE(SURFOBJ
* OutputObj
, CLIPOBJ
* Clip
,
107 BRUSHOBJ
* pbo
, LONG x
, LONG y
, LONG deltax
, LONG deltay
,
115 ULONG Pixel
= pbo
->iSolidColor
;
118 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_RIGHTUP
, 0);
119 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
120 TranslateRects(&RectEnum
, Translate
);
121 ClipRect
= RectEnum
.arcl
;
122 delta
= max(deltax
, deltay
);
125 while (i
< delta
&& (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
|| EnumMore
))
127 while ((ClipRect
< RectEnum
.arcl
+ RectEnum
.c
128 && (y
< ClipRect
->top
129 || (y
< ClipRect
->bottom
&& ClipRect
->right
<= x
)))
132 if (RectEnum
.arcl
+ RectEnum
.c
<= ClipRect
)
134 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
135 TranslateRects(&RectEnum
, Translate
);
136 ClipRect
= RectEnum
.arcl
;
143 if (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
)
145 if (ClipRect
->left
<= x
&& y
< ClipRect
->bottom
)
147 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_PutPixel(
148 OutputObj
, x
, y
, Pixel
);
153 error
= error
+ deltax
;
157 error
= error
- deltay
;
163 error
= error
+ deltay
;
167 error
= error
- deltax
;
176 NEtoSW(SURFOBJ
* OutputObj
, CLIPOBJ
* Clip
,
177 BRUSHOBJ
* pbo
, LONG x
, LONG y
, LONG deltax
, LONG deltay
,
185 ULONG Pixel
= pbo
->iSolidColor
;
188 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_LEFTDOWN
, 0);
189 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
190 TranslateRects(&RectEnum
, Translate
);
191 ClipRect
= RectEnum
.arcl
;
192 delta
= max(deltax
, deltay
);
195 while (i
< delta
&& (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
|| EnumMore
))
197 while ((ClipRect
< RectEnum
.arcl
+ RectEnum
.c
198 && (ClipRect
->bottom
<= y
199 || (ClipRect
->top
<= y
&& x
< ClipRect
->left
)))
202 if (RectEnum
.arcl
+ RectEnum
.c
<= ClipRect
)
204 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
205 TranslateRects(&RectEnum
, Translate
);
206 ClipRect
= RectEnum
.arcl
;
213 if (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
)
215 if (x
< ClipRect
->right
&& ClipRect
->top
<= y
)
217 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_PutPixel(
218 OutputObj
, x
, y
, Pixel
);
223 error
= error
+ deltax
;
227 error
= error
- deltay
;
233 error
= error
+ deltay
;
237 error
= error
- deltax
;
246 SEtoNW(SURFOBJ
* OutputObj
, CLIPOBJ
* Clip
,
247 BRUSHOBJ
* pbo
, LONG x
, LONG y
, LONG deltax
, LONG deltay
,
255 ULONG Pixel
= pbo
->iSolidColor
;
258 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_LEFTUP
, 0);
259 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
260 TranslateRects(&RectEnum
, Translate
);
261 ClipRect
= RectEnum
.arcl
;
262 delta
= max(deltax
, deltay
);
265 while (i
< delta
&& (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
|| EnumMore
))
267 while ((ClipRect
< RectEnum
.arcl
+ RectEnum
.c
268 && (y
< ClipRect
->top
269 || (y
< ClipRect
->bottom
&& x
< ClipRect
->left
)))
272 if (RectEnum
.arcl
+ RectEnum
.c
<= ClipRect
)
274 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
275 TranslateRects(&RectEnum
, Translate
);
276 ClipRect
= RectEnum
.arcl
;
283 if (ClipRect
< RectEnum
.arcl
+ RectEnum
.c
)
285 if (x
< ClipRect
->right
&& y
< ClipRect
->bottom
)
287 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_PutPixel(
288 OutputObj
, x
, y
, Pixel
);
293 error
= error
+ deltax
;
297 error
= error
- deltay
;
303 error
= error
+ deltay
;
307 error
= error
- deltax
;
320 _Inout_ SURFOBJ
*DestObj
,
327 _In_opt_ RECTL
*RectBounds
,
330 LONG x
, y
, deltax
, deltay
, xchange
, ychange
, hx
, vy
;
332 ULONG Pixel
= pbo
->iSolidColor
;
336 INTENG_ENTER_LEAVE EnterLeave
;
339 CLIPOBJ
*pcoPriv
= NULL
;
349 DestRect
.right
= x1
+ 1;
354 DestRect
.bottom
= y2
;
359 DestRect
.bottom
= y1
+ 1;
362 if (! IntEngEnter(&EnterLeave
, DestObj
, &DestRect
, FALSE
, &Translate
, &OutputObj
))
369 Clip
= pcoPriv
= EngCreateClip();
374 IntEngUpdateClipRegion((XCLIPOBJ
*)Clip
, 0, 0, RectBounds
);
387 if (0 == deltax
&& 0 == deltay
)
418 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_RIGHTDOWN
, 0);
421 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
422 for (i
= 0; i
< RectEnum
.c
&& RectEnum
.arcl
[i
].top
+ Translate
.y
<= y1
; i
++)
424 if (y1
< RectEnum
.arcl
[i
].bottom
+ Translate
.y
&&
425 RectEnum
.arcl
[i
].left
+ Translate
.x
<= hx
+ deltax
&&
426 hx
< RectEnum
.arcl
[i
].right
+ Translate
.x
&&
427 max(hx
, RectEnum
.arcl
[i
].left
+ Translate
.x
) <
428 min(hx
+ deltax
, RectEnum
.arcl
[i
].right
+ Translate
.x
))
430 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_HLine(
432 max(hx
, RectEnum
.arcl
[i
].left
+ Translate
.x
),
433 min(hx
+ deltax
, RectEnum
.arcl
[i
].right
+ Translate
.x
),
442 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, CD_RIGHTDOWN
, 0);
445 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
446 for (i
= 0; i
< RectEnum
.c
; i
++)
448 if (RectEnum
.arcl
[i
].left
+ Translate
.x
<= x1
&&
449 x1
< RectEnum
.arcl
[i
].right
+ Translate
.x
&&
450 RectEnum
.arcl
[i
].top
+ Translate
.y
<= vy
+ deltay
&&
451 vy
< RectEnum
.arcl
[i
].bottom
+ Translate
.y
)
453 DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_VLine(
455 max(vy
, RectEnum
.arcl
[i
].top
+ Translate
.y
),
456 min(vy
+ deltay
, RectEnum
.arcl
[i
].bottom
+ Translate
.y
),
469 NWtoSE(OutputObj
, Clip
, pbo
, x
, y
, deltax
, deltay
, &Translate
);
473 SWtoNE(OutputObj
, Clip
, pbo
, x
, y
, deltax
, deltay
, &Translate
);
480 NEtoSW(OutputObj
, Clip
, pbo
, x
, y
, deltax
, deltay
, &Translate
);
484 SEtoNW(OutputObj
, Clip
, pbo
, x
, y
, deltax
, deltay
, &Translate
);
491 EngDeleteClip(pcoPriv
);
494 return IntEngLeave(&EnterLeave
);
498 IntEngLineTo(SURFOBJ
*psoDest
,
514 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
517 GdiBrush
= CONTAINING_RECORD(
522 ASSERT(GdiBrush
->pbrush
);
524 if (GdiBrush
->pbrush
->flAttrs
& BR_IS_NULL
)
530 /* Clip lines totally outside the clip region. This is not done as an
531 * optimization (there are very few lines drawn outside the region) but
532 * as a workaround for what seems to be a problem in the CL54XX driver */
533 if (NULL
== ClipObj
|| DC_TRIVIAL
== ClipObj
->iDComplexity
)
536 b
.right
= psoDest
->sizlBitmap
.cx
;
538 b
.bottom
= psoDest
->sizlBitmap
.cy
;
542 b
= ClipObj
->rclBounds
;
544 if ((x1
< b
.left
&& x2
< b
.left
) || (b
.right
<= x1
&& b
.right
<= x2
) ||
545 (y1
< b
.top
&& y2
< b
.top
) || (b
.bottom
<= y1
&& b
.bottom
<= y2
))
550 b
.left
= min(x1
, x2
);
551 b
.right
= max(x1
, x2
);
553 b
.bottom
= max(y1
, y2
);
554 if (b
.left
== b
.right
) b
.right
++;
555 if (b
.top
== b
.bottom
) b
.bottom
++;
557 if (psurfDest
->flags
& HOOK_LINETO
)
559 /* Call the driver's DrvLineTo */
560 ret
= GDIDEVFUNCS(psoDest
).LineTo(
561 psoDest
, ClipObj
, pbo
, x1
, y1
, x2
, y2
, &b
, Mix
);
565 if (! ret
&& (psurfDest
->flags
& HOOK_STROKEPATH
))
567 /* FIXME: Emulate LineTo using drivers DrvStrokePath and set ret on success */
573 ret
= EngLineTo(psoDest
, ClipObj
, pbo
, x1
, y1
, x2
, y2
, RectBounds
, Mix
);
580 IntEngPolyline(SURFOBJ
*psoDest
,
591 // Draw the Polyline with a call to IntEngLineTo for each segment.
592 for (i
= 1; i
< dCount
; i
++)
594 rect
.left
= min(pt
[i
-1].x
, pt
[i
].x
);
595 rect
.top
= min(pt
[i
-1].y
, pt
[i
].y
);
596 rect
.right
= max(pt
[i
-1].x
, pt
[i
].x
);
597 rect
.bottom
= max(pt
[i
-1].y
, pt
[i
].y
);
598 ret
= IntEngLineTo(psoDest
,