ReactOS 0.4.15-dev-8222-g9164419
polyfill.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Various Polygon Filling routines for Polygon()
5 * FILE: win32ss/gdi/ntgdi/polyfill.c
6 * PROGRAMER: Mark Tempel
7 */
8
9#include <win32k.h>
10
11#define NDEBUG
12#include <debug.h>
13
14#define FILL_EDGE_ALLOC_TAG 0x45465044
15
16/*
17** This struct is used for book keeping during polygon filling routines.
18*/
19typedef struct _tagFILL_EDGE
20{
21 /* Basic line information */
22 int FromX;
23 int FromY;
24 int ToX;
25 int ToY;
26 int dx;
27 int dy;
28 int absdx, absdy;
29 int x, y;
30 int xmajor;
31
32 /* Active Edge List information */
33 int XIntercept[2];
34 int Error;
35 int ErrorMax;
37
38 /* The next edge in the active Edge List */
39 struct _tagFILL_EDGE * pNext;
41
42typedef struct _FILL_EDGE_LIST
43{
44 int Count;
47
48#if 0
49static
50void
52{
53 FILL_EDGE* pThis = list;
54 if (0 == list)
55 {
56 DPRINT1("List is NULL\n");
57 return;
58 }
59
60 while(0 != pThis)
61 {
62 //DPRINT1("EDGE: (%d, %d) to (%d, %d)\n", pThis->FromX, pThis->FromY, pThis->ToX, pThis->ToY);
63 DPRINT1("EDGE: [%d,%d]\n", pThis->XIntercept[0], pThis->XIntercept[1] );
64 pThis = pThis->pNext;
65 }
66}
67#else
68#define DEBUG_PRINT_ACTIVE_EDGELIST(x)
69#endif
70
71/*
72** Hide memory clean up.
73*/
74static
75void
78{
79 int i;
80
81 if (list)
82 {
83 if (list->Edges)
84 {
85 for (i = 0; i < list->Count; i++)
86 {
88 if (list->Edges[i])
89 EngFreeMem(list->Edges[i]);
90 }
91
92 EngFreeMem(list->Edges);
93 }
94
96 }
97}
98
99/*
100** This makes and initializes an Edge struct for a line between two points.
101*/
102static
106{
108
109 if (0 == rc)
110 return NULL;
111
112 //DPRINT1("Making Edge: (%d, %d) to (%d, %d)\n", From.x, From.y, To.x, To.y);
113 // Now fill the struct.
114 if ( To.y < From.y )
115 {
116 rc->FromX = To.x;
117 rc->FromY = To.y;
118 rc->ToX = From.x;
119 rc->ToY = From.y;
120 rc->YDirection = -1;
121
122 // Lines that go up get walked backwards, so need to be offset
123 // by -1 in order to make the walk identically on a pixel-level
124 rc->Error = -1;
125 }
126 else
127 {
128 rc->FromX = From.x;
129 rc->FromY = From.y;
130 rc->ToX = To.x;
131 rc->ToY = To.y;
132 rc->YDirection = 1;
133
134 rc->Error = 0;
135 }
136
137 rc->x = rc->FromX;
138 rc->y = rc->FromY;
139 rc->dx = rc->ToX - rc->FromX;
140 rc->dy = rc->ToY - rc->FromY;
141 rc->absdx = abs(rc->dx);
142 rc->absdy = abs(rc->dy);
143
144 rc->xmajor = rc->absdx > rc->absdy;
145
146 rc->ErrorMax = max(rc->absdx,rc->absdy);
147
148 rc->Error += rc->ErrorMax / 2;
149
150 rc->XDirection = (rc->dx < 0)?(-1):(1);
151
152 rc->pNext = 0;
153
154 //DPRINT("MakeEdge (%i,%i)->(%i,%i) d=(%i,%i) dir=(%i,%i) err=%i max=%i\n",
155 // From.x, From.y, To.x, To.y, rc->dx, rc->dy, rc->XDirection, rc->YDirection, rc->Error, rc->ErrorMax );
156
157 return rc;
158}
159/*
160** My Edge comparison routine.
161** This is for scan converting polygon fill.
162** First sort by MinY, then Minx, then slope.
163**
164** This comparison will help us determine which
165** lines will become active first when scanning from
166** top (min y) to bottom (max y).
167**
168** Return Value Meaning
169** Negative integer element1 < element2
170** Zero element1 = element2
171** Positive integer element1 > element2
172*/
173static
174INT
177{
178 int e1 = Edge1->XIntercept[0] + Edge1->XIntercept[1];
179 int e2 = Edge2->XIntercept[0] + Edge2->XIntercept[1];
180
181 return e1 - e2;
182}
183
184
185/*
186** Insert an edge into a list keeping the list in order.
187*/
188static
189void
192{
193 FILL_EDGE *pPrev, *pThis;
194 //DPRINT1("In POLYGONFILL_ActiveListInsert()\n");
195 ASSERT(activehead && NewEdge);
196
197 if (!*activehead)
198 {
199 NewEdge->pNext = NULL;
200 *activehead = NewEdge;
201 return;
202 }
203 /*
204 ** First lets check to see if we have a new smallest value.
205 */
206 if (FILL_EDGE_Compare(NewEdge, *activehead) <= 0)
207 {
208 NewEdge->pNext = *activehead;
209 *activehead = NewEdge;
210 return;
211 }
212
213 /*
214 ** Ok, now scan to the next spot to put this item.
215 */
216 pThis = *activehead;
217 pPrev = NULL;
218 while ( pThis && FILL_EDGE_Compare(pThis, NewEdge) < 0 )
219 {
220 pPrev = pThis;
221 pThis = pThis->pNext;
222 }
223
224 ASSERT(pPrev);
225 NewEdge->pNext = pPrev->pNext;
226 pPrev->pNext = NewEdge;
227 //DEBUG_PRINT_ACTIVE_EDGELIST(*activehead);
228}
229
230/*
231** Create a list of edges for a list of points.
232*/
233static
237{
238 int CurPt = 0;
239 FILL_EDGE_LIST* list = 0;
240 FILL_EDGE* e = 0;
241
242 if (0 == Points || 2 > Count)
243 return 0;
244
246 if ( 0 == list )
247 goto fail;
248 list->Count = 0;
250 if ( !list->Edges )
251 goto fail;
252
253 memset(list->Edges, 0, Count * sizeof(FILL_EDGE*));
254
255 for (CurPt = 1; CurPt < Count; ++CurPt)
256 {
257 e = POLYGONFILL_MakeEdge ( Points[CurPt-1], Points[CurPt] );
258 if (!e)
259 goto fail;
260
261 // If a straight horizontal line - who cares?
262 if (!e->absdy)
263 EngFreeMem(e);
264 else
265 list->Edges[list->Count++] = e;
266 }
267 e = POLYGONFILL_MakeEdge ( Points[CurPt-1], Points[0] );
268 if ( !e )
269 goto fail;
270
271 if (!e->absdy)
272 EngFreeMem(e);
273 else
274 list->Edges[list->Count++] = e;
275 return list;
276
277fail:
278
279 DPRINT1("Out Of MEMORY!!\n");
281 return 0;
282}
283
284
285/*
286** This slow routine uses the data stored in the edge list to
287** calculate the x intercepts for each line in the edge list
288** for scanline Scanline.
289**TODO: Get rid of this floating point arithmetic
290*/
291static
292void
295{
296 if (0 == pEdge->dy)
297 return;
298
299 ASSERT(pEdge->FromY <= Scanline && pEdge->ToY > Scanline);
300
301 if (pEdge->xmajor)
302 {
303 int steps;
304
305 ASSERT(pEdge->y == Scanline);
306
307 // Now shoot to end of scanline collision
308 steps = (pEdge->ErrorMax-pEdge->Error-1)/pEdge->absdy;
309 if (steps)
310 {
311 // Record first collision with scanline
312 int x1 = pEdge->x;
313 pEdge->x += steps * pEdge->XDirection;
314 pEdge->Error += steps * pEdge->absdy;
315 ASSERT ( pEdge->Error < pEdge->ErrorMax );
316 pEdge->XIntercept[0] = min(x1,pEdge->x);
317 pEdge->XIntercept[1] = max(x1,pEdge->x);
318 }
319 else
320 {
321 pEdge->XIntercept[0] = pEdge->x;
322 pEdge->XIntercept[1] = pEdge->x;
323 }
324
325 // We should require exactly 1 step to step onto next scanline...
326 ASSERT((pEdge->ErrorMax-pEdge->Error-1) / pEdge->absdy == 0);
327 pEdge->x += pEdge->XDirection;
328 pEdge->Error += pEdge->absdy;
329 ASSERT(pEdge->Error >= pEdge->ErrorMax);
330
331 // Now step onto next scanline...
332 pEdge->Error -= pEdge->absdx;
333 pEdge->y++;
334 }
335 else // Then this is a y-major line
336 {
337 pEdge->XIntercept[0] = pEdge->x;
338 pEdge->XIntercept[1] = pEdge->x;
339
340 pEdge->Error += pEdge->absdx;
341 pEdge->y++;
342
343 if (pEdge->Error >= pEdge->ErrorMax)
344 {
345 pEdge->Error -= pEdge->ErrorMax;
346 pEdge->x += pEdge->XDirection;
347 ASSERT ( pEdge->Error < pEdge->ErrorMax );
348 }
349 }
350
351 //DPRINT("Line (%d, %d) to (%d, %d) intersects scanline %d at (%d,%d)\n",
352 // pEdge->FromX, pEdge->FromY, pEdge->ToX, pEdge->ToY, Scanline, pEdge->XIntercept[0], pEdge->XIntercept[1] );
353}
354
355/*
356 * This method updates the Active edge collection for the scanline Scanline.
357 */
358static
359void
362 int Scanline,
364 FILL_EDGE** ActiveHead)
365{
366 int i;
367
368 ASSERT(list && ActiveHead);
369 *ActiveHead = 0;
370 for (i = 0; i < list->Count; i++)
371 {
372 FILL_EDGE* pEdge = list->Edges[i];
373 ASSERT(pEdge);
374 if (pEdge->FromY <= Scanline && pEdge->ToY > Scanline)
375 {
376 POLYGONFILL_UpdateScanline(pEdge, Scanline);
377 POLYGONFILL_ActiveListInsert(ActiveHead, pEdge);
378 }
379 }
380}
381
382/*
383** This method fills the portion of the polygon that intersects with the scanline
384** Scanline.
385*/
386static
387void
390 PDC dc,
391 int ScanLine,
392 FILL_EDGE* ActiveHead,
393 SURFACE *psurf,
394 BRUSHOBJ *BrushObj,
395 MIX RopMode )
396{
397 FILL_EDGE *pLeft, *pRight;
398
399 if (!ActiveHead)
400 return;
401
402 pLeft = ActiveHead;
403 pRight = pLeft->pNext;
404 ASSERT(pRight);
405
406 while (NULL != pRight)
407 {
408 int x1 = pLeft->XIntercept[0];
409 int x2 = pRight->XIntercept[1];
410 if (x2 > x1)
411 {
412 RECTL BoundRect;
413 BoundRect.top = ScanLine;
414 BoundRect.bottom = ScanLine + 1;
415 BoundRect.left = x1;
416 BoundRect.right = x2;
417
418 //DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
419 IntEngLineTo(&psurf->SurfObj,
420 (CLIPOBJ *)&dc->co,
421 BrushObj,
422 x1,
423 ScanLine,
424 x2,
425 ScanLine,
426 &BoundRect, // Bounding rectangle
427 RopMode); // MIX
428 }
429 pLeft = pRight->pNext;
430 pRight = pLeft ? pLeft->pNext : NULL;
431 }
432}
433
434static
435void
438 PDC dc,
439 int ScanLine,
440 FILL_EDGE* ActiveHead,
441 SURFACE *psurf,
442 BRUSHOBJ *BrushObj,
443 MIX RopMode )
444{
445 FILL_EDGE *pLeft, *pRight;
446 int x1, x2, winding = 0;
447 RECTL BoundRect;
448
449 if (!ActiveHead)
450 return;
451
452 BoundRect.top = ScanLine;
453 BoundRect.bottom = ScanLine + 1;
454
455 pLeft = ActiveHead;
456 winding = pLeft->YDirection;
457 pRight = pLeft->pNext;
458 ASSERT(pRight);
459
460 // Setup first line...
461 x1 = pLeft->XIntercept[0];
462 x2 = pRight->XIntercept[1];
463
464 pLeft = pRight;
465 pRight = pLeft->pNext;
466 winding += pLeft->YDirection;
467
468 while ( NULL != pRight )
469 {
470 int newx1 = pLeft->XIntercept[0];
471 int newx2 = pRight->XIntercept[1];
472 if ( winding )
473 {
474 // Check and see if this new line touches the previous...
475 if ((newx1 >= x1 && newx1 <= x2) ||
476 (newx2 >= x1 && newx2 <= x2) ||
477 (x1 >= newx1 && x1 <= newx2) ||
478 (x2 >= newx2 && x2 <= newx2))
479 {
480 // Yup, just tack it on to our existing line
481 x1 = min(x1,newx1);
482 x2 = max(x2,newx2);
483 }
484 else
485 {
486 // Nope - render the old line..
487 BoundRect.left = x1;
488 BoundRect.right = x2;
489
490 //DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
491 IntEngLineTo(&psurf->SurfObj,
492 (CLIPOBJ *)&dc->co,
493 BrushObj,
494 x1,
495 ScanLine,
496 x2,
497 ScanLine,
498 &BoundRect, // Bounding rectangle
499 RopMode); // MIX
500
501 x1 = newx1;
502 x2 = newx2;
503 }
504 }
505
506 pLeft = pRight;
507 pRight = pLeft->pNext;
508 winding += pLeft->YDirection;
509 }
510
511 // There will always be a line left-over, render it now...
512 BoundRect.left = x1;
513 BoundRect.right = x2;
514
515 //DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
516 IntEngLineTo(&psurf->SurfObj,
517 (CLIPOBJ *)&dc->co,
518 BrushObj,
519 x1,
520 ScanLine,
521 x2,
522 ScanLine,
523 &BoundRect, // Bounding rectangle
524 RopMode); // MIX
525}
526
527// When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and
528// even-numbered polygon sides on each scan line. That is, GDI fills the area between the
529// first and second side, between the third and fourth side, and so on.
530
531// WINDING Selects winding mode (fills any region with a nonzero winding value).
532// When the fill mode is WINDING, GDI fills any region that has a nonzero winding value.
533// This value is defined as the number of times a pen used to draw the polygon would go around the region.
534// The direction of each edge of the polygon is important.
535
536BOOL
539 PDC dc,
540 SURFACE *psurf,
541 BRUSHOBJ *BrushObj,
542 MIX RopMode,
543 CONST PPOINT Points,
544 int Count,
545 RECTL BoundRect )
546{
547 FILL_EDGE_LIST *list = 0;
548 FILL_EDGE *ActiveHead = 0;
549 int ScanLine;
550 PDC_ATTR pdcattr = dc->pdcattr;
551 void
552 (APIENTRY *FillScanLine)(
553 PDC dc,
554 int ScanLine,
555 FILL_EDGE* ActiveHead,
556 SURFACE *psurf,
557 BRUSHOBJ *BrushObj,
558 MIX RopMode);
559
560 //DPRINT("FillPolygon\n");
561
562 /* Create Edge List. */
564 /* DEBUG_PRINT_EDGELIST(list); */
565 if (NULL == list)
566 return FALSE;
567
568 if (WINDING == pdcattr->jFillMode)
569 FillScanLine = POLYGONFILL_FillScanLineWinding;
570 else /* Default */
572
573 /* For each Scanline from BoundRect.bottom to BoundRect.top,
574 * determine line segments to draw
575 */
576 for (ScanLine = BoundRect.top; ScanLine < BoundRect.bottom; ++ScanLine)
577 {
578 POLYGONFILL_BuildActiveList(ScanLine, list, &ActiveHead);
579 //DEBUG_PRINT_ACTIVE_EDGELIST(ActiveHead);
580 FillScanLine(dc, ScanLine, ActiveHead, psurf, BrushObj, RopMode);
581 }
582
583 /* Free Edge List. If any are left. */
585
586 return TRUE;
587}
588
591 PDC dc,
592 SURFACE *psurf,
593 BRUSHOBJ *BrushObj,
594 CONST PPOINT Points,
595 int Count,
596 RECTL DestRect,
597 POINTL *BrushOrigin)
598{
599 FILL_EDGE_LIST *list = 0;
600 FILL_EDGE *ActiveHead = 0;
601 FILL_EDGE *pLeft, *pRight;
602 int ScanLine;
603
604 //DPRINT("IntFillPolygon\n");
605
606 /* Create Edge List. */
608 /* DEBUG_PRINT_EDGELIST(list); */
609 if (NULL == list)
610 return FALSE;
611
612 /* For each Scanline from DestRect.top to DestRect.bottom, determine line segments to draw */
613 for (ScanLine = DestRect.top; ScanLine < DestRect.bottom; ++ScanLine)
614 {
615 POLYGONFILL_BuildActiveList(ScanLine, list, &ActiveHead);
616 //DEBUG_PRINT_ACTIVE_EDGELIST(ActiveHead);
617
618 if (!ActiveHead)
619 {
621 return FALSE;
622 }
623
624 pLeft = ActiveHead;
625 pRight = pLeft->pNext;
626 ASSERT(pRight);
627
628 while (NULL != pRight)
629 {
630 int x1 = pLeft->XIntercept[0];
631 int x2 = pRight->XIntercept[1];
632
633 if (x2 > x1)
634 {
635 RECTL LineRect;
636 LineRect.top = ScanLine;
637 LineRect.bottom = ScanLine + 1;
638 LineRect.left = x1;
639 LineRect.right = x2;
640
641 IntEngBitBlt(&psurf->SurfObj,
642 NULL,
643 NULL,
644 (CLIPOBJ *)&dc->co,
645 NULL,
646 &LineRect,
647 NULL,
648 NULL,
649 BrushObj,
650 BrushOrigin,
652 }
653
654 pLeft = pRight->pNext;
655 pRight = pLeft ? pLeft->pNext : NULL;
656 }
657 }
658
659 /* Free Edge List. If any are left. */
661
662 return TRUE;
663}
664
665/* EOF */
#define WINDING
Definition: constants.h:279
#define DPRINT1
Definition: precomp.h:8
Definition: list.h:37
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define APIENTRY
Definition: api.h:79
#define abs(i)
Definition: fconv.c:206
unsigned int BOOL
Definition: ntddk_ex.h:94
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ROP4_FROM_INDEX(index)
Definition: inteng.h:42
@ R3_OPINDEX_PATCOPY
Definition: inteng.h:35
#define e
Definition: ke_i.h:82
if(dx< 0)
Definition: linetemp.h:194
static const WCHAR dc[]
#define ASSERT(a)
Definition: mode.c:44
static DWORD DWORD DWORD DWORD * steps
Definition: cursoricon.c:1638
#define min(a, b)
Definition: monoChain.cc:55
int Count
Definition: noreturn.cpp:7
#define FASTCALL
Definition: nt_native.h:50
#define CONST
Definition: pedump.c:81
#define DEBUG_PRINT_ACTIVE_EDGELIST(x)
Definition: polyfill.c:68
static FILL_EDGE *FASTCALL POLYGONFILL_MakeEdge(POINT From, POINT To)
Definition: polyfill.c:105
static void APIENTRY POLYGONFILL_FillScanLineAlternate(PDC dc, int ScanLine, FILL_EDGE *ActiveHead, SURFACE *psurf, BRUSHOBJ *BrushObj, MIX RopMode)
Definition: polyfill.c:389
static void APIENTRY POLYGONFILL_FillScanLineWinding(PDC dc, int ScanLine, FILL_EDGE *ActiveHead, SURFACE *psurf, BRUSHOBJ *BrushObj, MIX RopMode)
Definition: polyfill.c:437
static FILL_EDGE_LIST *FASTCALL POLYGONFILL_MakeEdgeList(PPOINT Points, int Count)
Definition: polyfill.c:236
struct _FILL_EDGE_LIST FILL_EDGE_LIST
#define FILL_EDGE_ALLOC_TAG
Definition: polyfill.c:14
struct _tagFILL_EDGE FILL_EDGE
BOOL FASTCALL IntFillPolygon(PDC dc, SURFACE *psurf, BRUSHOBJ *BrushObj, CONST PPOINT Points, int Count, RECTL DestRect, POINTL *BrushOrigin)
Definition: polyfill.c:590
static void FASTCALL POLYGONFILL_DestroyEdgeList(FILL_EDGE_LIST *list)
Definition: polyfill.c:77
static void APIENTRY POLYGONFILL_BuildActiveList(int Scanline, FILL_EDGE_LIST *list, FILL_EDGE **ActiveHead)
Definition: polyfill.c:361
static void FASTCALL POLYGONFILL_ActiveListInsert(FILL_EDGE **activehead, FILL_EDGE *NewEdge)
Definition: polyfill.c:191
BOOL APIENTRY FillPolygon(PDC dc, SURFACE *psurf, BRUSHOBJ *BrushObj, MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect)
Definition: polyfill.c:538
static void FASTCALL POLYGONFILL_UpdateScanline(FILL_EDGE *pEdge, int Scanline)
Definition: polyfill.c:294
static INT FASTCALL FILL_EDGE_Compare(FILL_EDGE *Edge1, FILL_EDGE *Edge2)
Definition: polyfill.c:176
#define EngFreeMem
Definition: polytest.cpp:56
#define FL_ZERO_MEMORY
Definition: polytest.cpp:58
void IntEngLineTo(SURFOBJ *, CLIPOBJ, PBRUSHOBJ, int x1, int y1, int x2, int y2, RECTL *, MIX mix)
Definition: polytest.cpp:107
void * EngAllocMem(int zero, unsigned long size, int tag=0)
Definition: polytest.cpp:70
#define list
Definition: rosglue.h:35
#define memset(x, y, z)
Definition: compat.h:39
Definition: polytest.cpp:41
long bottom
Definition: polytest.cpp:53
long right
Definition: polytest.cpp:53
long top
Definition: polytest.cpp:53
long left
Definition: polytest.cpp:53
BYTE jFillMode
Definition: ntgdihdl.h:309
FILL_EDGE ** Edges
Definition: polytest.cpp:198
SURFOBJ SurfObj
Definition: surface.h:8
struct _tagFILL_EDGE * pNext
Definition: polytest.cpp:192
int XIntercept[2]
Definition: polytest.cpp:186
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
#define _PRAGMA_WARNING_SUPPRESS(x)
Definition: suppress.h:28
#define __WARNING_USING_UNINIT_VAR
Definition: suppress.h:31
#define max(a, b)
Definition: svc.c:63
int32_t INT
Definition: typedefs.h:58
BOOL APIENTRY IntEngBitBlt(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo, RECTL *prclTrg, POINTL *pptlSrc, POINTL *pptlMask, BRUSHOBJ *pbo, POINTL *pptlBrush, ROP4 Rop4)
Definition: bitblt.c:656
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3710
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708
ULONG MIX
Definition: winddi.h:129