ReactOS  r76032
path.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS win32 kernel mode subsystem
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: win32ss/gdi/ntgdi/path.c
5  * PURPOSE: Graphics paths (BeginPath, EndPath etc.)
6  * PROGRAMMER: Copyright 1997, 1998 Martin Boehme
7  * 1999 Huw D M Davies
8  * 2005 Dmitry Timoshkov
9  */
10 
11 #include <win32k.h>
12 #include <suppress.h>
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 #ifdef _MSC_VER
18 #pragma warning(disable:4244)
19 #endif
20 
21 #define NUM_ENTRIES_INITIAL 16 /* Initial size of points / flags arrays */
22 
23 #define GROW_FACTOR_NUMER 2 /* Numerator of grow factor for the array */
24 #define GROW_FACTOR_DENOM 1 /* Denominator of grow factor */
25 
26 #if DBG
27 static int PathCount = 0;
28 #endif
29 
30 /***********************************************************************
31  * Internal functions
32  */
33 
36 {
38 
39  if (!pPath)
40  {
42  return NULL;
43  }
44 
45  DPRINT("CreatePath p 0x%p\n", pPath);
46  // Path handles are shared. Also due to recursion with in the same thread.
47  GDIOBJ_vUnlockObject((POBJ)pPath); // Unlock
48  pPath = PATH_LockPath(pPath->BaseObject.hHmgr); // Share Lock.
49 
50  /* Make sure that path is empty */
51  PATH_EmptyPath(pPath);
52 
53  count = max( NUM_ENTRIES_INITIAL, count );
54 
55  pPath->numEntriesAllocated = count;
56 
57  pPath->pPoints = (POINT *)ExAllocatePoolWithTag(PagedPool, count * sizeof(POINT), TAG_PATH);
58  RtlZeroMemory( pPath->pPoints, count * sizeof(POINT));
59  pPath->pFlags = (BYTE *)ExAllocatePoolWithTag(PagedPool, count * sizeof(BYTE), TAG_PATH);
60  RtlZeroMemory( pPath->pFlags, count * sizeof(BYTE));
61 
62  /* Initialize variables for new path */
63  pPath->numEntriesUsed = 0;
64  pPath->newStroke = TRUE;
65  pPath->state = PATH_Open;
66  pPath->pos.x = pPath->pos.y = 0;
67 #if DBG
68  PathCount++;
69  DPRINT("Create Path %d\n",PathCount);
70 #endif
71  return pPath;
72 }
73 
74 /* PATH_DestroyGdiPath
75  *
76  * Destroys a GdiPath structure (frees the memory in the arrays).
77  */
78 VOID
81 {
82  ASSERT(pPath != NULL);
83 
84  if (pPath->pPoints) ExFreePoolWithTag(pPath->pPoints, TAG_PATH);
85  if (pPath->pFlags) ExFreePoolWithTag(pPath->pFlags, TAG_PATH);
86 }
87 
88 BOOL
91 {
92  PPATH pPath;
93  if (!hPath) return FALSE;
94  pPath = PATH_LockPath(hPath);
95  if (!pPath) return FALSE;
96  PATH_DestroyGdiPath(pPath);
98 #if DBG
99  PathCount--;
100  DPRINT("Delete Path %d\n",PathCount);
101 #endif
102  return TRUE;
103 }
104 
105 
106 VOID
107 FASTCALL
109 {
110  ASSERT(pPath->state == PATH_Open);
111 
112  // FIXME: Shouldn't we draw a line to the beginning of the figure?
113  // Set PT_CLOSEFIGURE on the last entry and start a new stroke
114  if (pPath->numEntriesUsed)
115  {
116  pPath->pFlags[pPath->numEntriesUsed - 1] |= PT_CLOSEFIGURE;
117  pPath->newStroke = TRUE;
118  }
119 }
120 
121 /* MSDN: This fails if the device coordinates exceed 27 bits, or if the converted
122  logical coordinates exceed 32 bits. */
123 BOOL
124 FASTCALL
126  PDC pdc,
127  PPOINT ppt,
128  INT count)
129 {
130  XFORMOBJ xo;
131 
132  XFORMOBJ_vInit(&xo, &pdc->pdcattr->mxDeviceToWorld);
133  return XFORMOBJ_bApplyXform(&xo, XF_LTOL, count, (PPOINTL)ppt, (PPOINTL)ppt);
134 }
135 
136 /* PATH_InitGdiPath
137  *
138  * Initializes the GdiPath structure.
139  */
140 VOID
141 FASTCALL
143  PPATH pPath)
144 {
145  ASSERT(pPath != NULL);
146 
147  pPath->state = PATH_Null;
148  pPath->pPoints = NULL;
149  pPath->pFlags = NULL;
150  pPath->numEntriesUsed = 0;
151  pPath->numEntriesAllocated = 0;
152 }
153 
154 /* PATH_AssignGdiPath
155  *
156  * Copies the GdiPath structure "pPathSrc" to "pPathDest". A deep copy is
157  * performed, i.e. the contents of the pPoints and pFlags arrays are copied,
158  * not just the pointers. Since this means that the arrays in pPathDest may
159  * need to be resized, pPathDest should have been initialized using
160  * PATH_InitGdiPath (in C++, this function would be an assignment operator,
161  * not a copy constructor).
162  * Returns TRUE if successful, else FALSE.
163  */
164 BOOL
165 FASTCALL
167  PPATH pPathDest,
168  const PPATH pPathSrc)
169 {
170  ASSERT(pPathDest != NULL && pPathSrc != NULL);
171 
172  /* Make sure destination arrays are big enough */
173  if (!PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed))
174  return FALSE;
175 
176  /* Perform the copy operation */
177  memcpy(pPathDest->pPoints, pPathSrc->pPoints, sizeof(POINT)*pPathSrc->numEntriesUsed);
178  memcpy(pPathDest->pFlags, pPathSrc->pFlags, sizeof(BYTE)*pPathSrc->numEntriesUsed);
179 
180  pPathDest->pos = pPathSrc->pos;
181  pPathDest->state = pPathSrc->state;
182  pPathDest->numEntriesUsed = pPathSrc->numEntriesUsed;
183  pPathDest->newStroke = pPathSrc->newStroke;
184  return TRUE;
185 }
186 
188 {
189  PPATH pdstPath, psrcPath = PATH_LockPath(src->dclevel.hPath);
190  DPRINT("PATH_SavePath\n");
191  if (psrcPath)
192  {
193  DPRINT("PATH_SavePath 1\n");
194 
195  pdstPath = PATH_CreatePath(psrcPath->numEntriesAllocated);
196 
197  dst->dclevel.flPath = src->dclevel.flPath;
198 
199  dst->dclevel.hPath = pdstPath->BaseObject.hHmgr;
200 
201  PATH_AssignGdiPath(pdstPath, psrcPath);
202 
203  PATH_UnlockPath(pdstPath);
204  PATH_UnlockPath(psrcPath);
205  }
206  return TRUE;
207 }
208 
210 {
211  DPRINT("PATH_RestorePath\n");
212 
213  if (dst->dclevel.hPath == NULL)
214  {
215  PPATH pdstPath, psrcPath = PATH_LockPath(src->dclevel.hPath);
216  DPRINT("PATH_RestorePath 1\n");
217  pdstPath = PATH_CreatePath(psrcPath->numEntriesAllocated);
218  dst->dclevel.flPath = src->dclevel.flPath;
219  dst->dclevel.hPath = pdstPath->BaseObject.hHmgr;
220 
221  PATH_AssignGdiPath(pdstPath, psrcPath);
222 
223  PATH_UnlockPath(pdstPath);
224  PATH_UnlockPath(psrcPath);
225  }
226  else
227  {
228  PPATH pdstPath, psrcPath = PATH_LockPath(src->dclevel.hPath);
229  pdstPath = PATH_LockPath(dst->dclevel.hPath);
230  DPRINT("PATH_RestorePath 2\n");
231  dst->dclevel.flPath = src->dclevel.flPath & (DCPATH_CLOCKWISE|DCPATH_ACTIVE);
232  PATH_AssignGdiPath(pdstPath, psrcPath);
233 
234  PATH_UnlockPath(pdstPath);
235  PATH_UnlockPath(psrcPath);
236  }
237  return TRUE;
238 }
239 
240 /* PATH_EmptyPath
241  *
242  * Removes all entries from the path and sets the path state to PATH_Null.
243  */
244 VOID
245 FASTCALL
247 {
248  ASSERT(pPath != NULL);
249 
250  pPath->state = PATH_Null;
251  pPath->numEntriesUsed = 0;
252 }
253 
254 /* PATH_AddEntry
255  *
256  * Adds an entry to the path. For "flags", pass either PT_MOVETO, PT_LINETO
257  * or PT_BEZIERTO, optionally ORed with PT_CLOSEFIGURE. Returns TRUE if
258  * successful, FALSE otherwise (e.g. if not enough memory was available).
259  */
260 BOOL
261 FASTCALL
263  PPATH pPath,
264  const POINT *pPoint,
265  BYTE flags)
266 {
267  ASSERT(pPath != NULL);
268 
269  /* FIXME: If newStroke is true, perhaps we want to check that we're
270  * getting a PT_MOVETO
271  */
272  DPRINT("(%d,%d) - %d\n", pPoint->x, pPoint->y, flags);
273 
274  /* Reserve enough memory for an extra path entry */
275  if (!PATH_ReserveEntries(pPath, pPath->numEntriesUsed + 1))
276  return FALSE;
277 
278  /* Store information in path entry */
279  pPath->pPoints[pPath->numEntriesUsed] = *pPoint;
280  pPath->pFlags[pPath->numEntriesUsed] = flags;
281 
282  /* Increment entry count */
283  pPath->numEntriesUsed++;
284 
285  return TRUE;
286 }
287 
288 /* PATH_ReserveEntries
289  *
290  * Ensures that at least "numEntries" entries (for points and flags) have
291  * been allocated; allocates larger arrays and copies the existing entries
292  * to those arrays, if necessary. Returns TRUE if successful, else FALSE.
293  */
294 BOOL
295 FASTCALL
297  PPATH pPath,
298  INT numEntries)
299 {
300  INT numEntriesToAllocate;
301  POINT *pPointsNew;
302  BYTE *pFlagsNew;
303 
304  ASSERT(pPath != NULL);
305  ASSERT(numEntries >= 0);
306 
307  /* Do we have to allocate more memory? */
308  if (numEntries > pPath->numEntriesAllocated)
309  {
310  /* Find number of entries to allocate. We let the size of the array
311  * grow exponentially, since that will guarantee linear time
312  * complexity. */
313  if (pPath->numEntriesAllocated)
314  {
315  numEntriesToAllocate = pPath->numEntriesAllocated;
316  while (numEntriesToAllocate < numEntries)
317  numEntriesToAllocate = numEntriesToAllocate * GROW_FACTOR_NUMER / GROW_FACTOR_DENOM;
318  }
319  else
320  numEntriesToAllocate = numEntries;
321 
322  /* Allocate new arrays */
323  pPointsNew = (POINT *)ExAllocatePoolWithTag(PagedPool, numEntriesToAllocate * sizeof(POINT), TAG_PATH);
324  if (!pPointsNew)
325  return FALSE;
326 
327  pFlagsNew = (BYTE *)ExAllocatePoolWithTag(PagedPool, numEntriesToAllocate * sizeof(BYTE), TAG_PATH);
328  if (!pFlagsNew)
329  {
330  ExFreePoolWithTag(pPointsNew, TAG_PATH);
331  return FALSE;
332  }
333 
334  /* Copy old arrays to new arrays and discard old arrays */
335  if (pPath->pPoints)
336  {
337  ASSERT(pPath->pFlags);
338 
339  memcpy(pPointsNew, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
340  memcpy(pFlagsNew, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
341 
344  }
345 
346  pPath->pPoints = pPointsNew;
347  pPath->pFlags = pFlagsNew;
348  pPath->numEntriesAllocated = numEntriesToAllocate;
349  }
350 
351  return TRUE;
352 }
353 
354 /* PATH_ScaleNormalizedPoint
355  *
356  * Scales a normalized point (x, y) with respect to the box whose corners are
357  * passed in "corners". The point is stored in "*pPoint". The normalized
358  * coordinates (-1.0, -1.0) correspond to corners[0], the coordinates
359  * (1.0, 1.0) correspond to corners[1].
360  */
361 VOID
362 FASTCALL
364  FLOAT_POINT corners[],
365  double x,
366  double y,
367  POINT *pPoint)
368 {
369  ASSERT(corners);
370  ASSERT(pPoint);
371 
372  pPoint->x = GDI_ROUND((double)corners[0].x + (double)(corners[1].x - corners[0].x) * 0.5 * (x + 1.0));
373  pPoint->y = GDI_ROUND((double)corners[0].y + (double)(corners[1].y - corners[0].y) * 0.5 * (y + 1.0));
374 }
375 
376 /* PATH_NormalizePoint
377  *
378  * Normalizes a point with respect to the box whose corners are passed in
379  * corners. The normalized coordinates are stored in *pX and *pY.
380  */
381 VOID
382 FASTCALL
384  FLOAT_POINT corners[],
385  const FLOAT_POINT *pPoint,
386  double *pX,
387  double *pY)
388 {
389  ASSERT(corners);
390  ASSERT(pPoint);
391  ASSERT(pX);
392  ASSERT(pY);
393 
394  *pX = (double)(pPoint->x - corners[0].x) / (double)(corners[1].x - corners[0].x) * 2.0 - 1.0;
395  *pY = (double)(pPoint->y - corners[0].y) / (double)(corners[1].y - corners[0].y) * 2.0 - 1.0;
396 }
397 
398 /* PATH_CheckCorners
399  *
400  * Helper function for PATH_RoundRect() and PATH_Rectangle()
401  */
402 BOOL
404  DC *dc,
405  POINT corners[],
406  INT x1,
407  INT y1,
408  INT x2,
409  INT y2)
410 {
411  INT temp;
412  PDC_ATTR pdcattr = dc->pdcattr;
413 
414  /* Convert points to device coordinates */
415  corners[0].x = x1;
416  corners[0].y = y1;
417  corners[1].x = x2;
418  corners[1].y = y2;
419  IntLPtoDP(dc, corners, 2);
420 
421  /* Make sure first corner is top left and second corner is bottom right */
422  if (corners[0].x > corners[1].x)
423  {
424  temp = corners[0].x;
425  corners[0].x = corners[1].x;
426  corners[1].x = temp;
427  }
428 
429  if (corners[0].y > corners[1].y)
430  {
431  temp = corners[0].y;
432  corners[0].y = corners[1].y;
433  corners[1].y = temp;
434  }
435 
436  /* In GM_COMPATIBLE, don't include bottom and right edges */
437  if (pdcattr->iGraphicsMode == GM_COMPATIBLE)
438  {
439  if (corners[0].x == corners[1].x) return FALSE;
440  if (corners[0].y == corners[1].y) return FALSE;
441  corners[1].x--;
442  corners[1].y--;
443  }
444  return TRUE;
445 }
446 
447 /* add a number of points, converting them to device coords */
448 /* return a pointer to the first type byte so it can be fixed up if necessary */
450  DWORD count, BYTE type )
451 {
452  BYTE *ret;
453 
454  if (!PATH_ReserveEntries( path, path->numEntriesUsed + count )) return NULL;
455 
456  ret = &path->pFlags[path->numEntriesUsed];
457  memcpy( &path->pPoints[path->numEntriesUsed], points, count * sizeof(*points) );
458  IntLPtoDP( dc, &path->pPoints[path->numEntriesUsed], count );
459  memset( ret, type, count );
460  path->numEntriesUsed += count;
461  return ret;
462 }
463 
464 /* add a number of points that are already in device coords */
465 /* return a pointer to the first type byte so it can be fixed up if necessary */
467 {
468  BYTE *ret;
469 
470  if (!PATH_ReserveEntries( path, path->numEntriesUsed + count )) return NULL;
471 
472  ret = &path->pFlags[path->numEntriesUsed];
473  memcpy( &path->pPoints[path->numEntriesUsed], points, count * sizeof(*points) );
474  memset( ret, type, count );
475  path->numEntriesUsed += count;
476  return ret;
477 }
478 
479 /* reverse the order of an array of points */
481 {
482  UINT i;
483  for (i = 0; i < count / 2; i++)
484  {
485  POINT pt = points[i];
486  points[i] = points[count - i - 1];
487  points[count - i - 1] = pt;
488  }
489 }
490 
491 /* start a new path stroke if necessary */
493 {
494  if (!path->newStroke && path->numEntriesUsed &&
495  !(path->pFlags[path->numEntriesUsed - 1] & PT_CLOSEFIGURE) &&
496  path->pPoints[path->numEntriesUsed - 1].x == path->pos.x &&
497  path->pPoints[path->numEntriesUsed - 1].y == path->pos.y)
498  return TRUE;
499 
500  path->newStroke = FALSE;
501  return add_points( path, &path->pos, 1, PT_MOVETO ) != NULL;
502 }
503 
504 /* set current position to the last point that was added to the path */
506 {
507  assert( path->numEntriesUsed );
508  path->pos = path->pPoints[path->numEntriesUsed - 1];
509 }
510 
511 /* close the current figure */
512 static void close_figure( PPATH path )
513 {
514  assert( path->numEntriesUsed );
515  path->pFlags[path->numEntriesUsed - 1] |= PT_CLOSEFIGURE;
516 }
517 
518 /* add a number of points, starting a new stroke if necessary */
520  DWORD count, BYTE type )
521 {
522  if (!start_new_stroke( path )) return FALSE;
523  if (!add_log_points( dc, path, points, count, type )) return FALSE;
524  update_current_pos( path );
525 
526  DPRINT("ALPNS : Pos X %d Y %d\n",path->pos.x, path->pos.y);
527  IntGdiMoveToEx(dc, path->pos.x, path->pos.y, NULL);
528 
529  return TRUE;
530 }
531 
532 /* PATH_MoveTo
533  *
534  * Should be called when a MoveTo is performed on a DC that has an
535  * open path. This starts a new stroke. Returns TRUE if successful, else
536  * FALSE.
537  */
538 BOOL
539 FASTCALL
541  PDC dc,
542  PPATH pPath)
543 {
544  if (!pPath) return FALSE;
545 
546  // GDI32 : Signal from user space of a change in position.
547  if (dc->pdcattr->ulDirty_ & DIRTY_STYLESTATE)
548  {
549  DPRINT("MoveTo has changed\n");
550  pPath->newStroke = TRUE;
551  // Set position and clear the signal flag.
552  IntGetCurrentPositionEx(dc, &pPath->pos);
553  IntLPtoDP( dc, &pPath->pos, 1 );
554  return TRUE;
555  }
556 
557  return FALSE;
558 }
559 
560 /* PATH_LineTo
561  *
562  * Should be called when a LineTo is performed on a DC that has an
563  * open path. This adds a PT_LINETO entry to the path (and possibly
564  * a PT_MOVETO entry, if this is the first LineTo in a stroke).
565  * Returns TRUE if successful, else FALSE.
566  */
567 BOOL
568 FASTCALL
570  PDC dc,
571  INT x,
572  INT y)
573 {
574  BOOL Ret;
575  PPATH pPath;
576  POINT point, pointCurPos;
577 
578  pPath = PATH_LockPath(dc->dclevel.hPath);
579  if (!pPath) return FALSE;
580 
581  point.x = x;
582  point.y = y;
583 
584  // Coalesce a MoveTo point.
585  if ( !PATH_MoveTo(dc, pPath) )
586  {
587  /* Add a PT_MOVETO if necessary */
588  if (pPath->newStroke)
589  {
590  DPRINT("Line To : New Stroke\n");
591  pPath->newStroke = FALSE;
592  IntGetCurrentPositionEx(dc, &pointCurPos);
593  CoordLPtoDP(dc, &pointCurPos);
594  if (!PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO))
595  {
596  PATH_UnlockPath(pPath);
597  return FALSE;
598  }
599  }
600  }
601  Ret = add_log_points_new_stroke( dc, pPath, &point, 1, PT_LINETO );
602  PATH_UnlockPath(pPath);
603  return Ret;
604 }
605 
606 /* PATH_Rectangle
607  *
608  * Should be called when a call to Rectangle is performed on a DC that has
609  * an open path. Returns TRUE if successful, else FALSE.
610  */
611 BOOL
612 FASTCALL
614  PDC dc,
615  INT x1,
616  INT y1,
617  INT x2,
618  INT y2)
619 {
620  PPATH pPath;
621  POINT corners[2], points[4];
622  BYTE *type;
623 
624  pPath = PATH_LockPath(dc->dclevel.hPath);
625  if (!pPath) return FALSE;
626 
627  if (!PATH_CheckCorners(dc, corners, x1, y1, x2, y2))
628  {
629  PATH_UnlockPath(pPath);
630  return TRUE;
631  }
632 
633  points[0].x = corners[1].x;
634  points[0].y = corners[0].y;
635  points[1] = corners[0];
636  points[2].x = corners[0].x;
637  points[2].y = corners[1].y;
638  points[3] = corners[1];
639 
640  if (dc->dclevel.flPath & DCPATH_CLOCKWISE) reverse_points( points, 4 );
641 
642  if (!(type = add_points( pPath, points, 4, PT_LINETO )))
643  {
644  PATH_UnlockPath(pPath);
645  return FALSE;
646  }
647  type[0] = PT_MOVETO;
648 
649  /* Close the rectangle figure */
650  IntGdiCloseFigure(pPath) ;
651  PATH_UnlockPath(pPath);
652  return TRUE;
653 }
654 
655 /* PATH_RoundRect
656  *
657  * Should be called when a call to RoundRect is performed on a DC that has
658  * an open path. Returns TRUE if successful, else FALSE.
659  *
660  */
661 BOOL
662 FASTCALL
664  DC *dc,
665  INT x1,
666  INT y1,
667  INT x2,
668  INT y2,
669  INT ell_width,
670  INT ell_height)
671 {
672  const double factor = 0.55428475; /* 4 / 3 * (sqrt(2) - 1) */
673  PPATH pPath;
674  POINT corners[2], ellipse[2], points[16];
675  BYTE *type;
676  double width, height;
677 
678  if (!ell_width || !ell_height) return PATH_Rectangle( dc, x1, y1, x2, y2 );
679 
680  pPath = PATH_LockPath(dc->dclevel.hPath);
681  if (!pPath) return FALSE;
682 
683  if (!PATH_CheckCorners(dc, corners, x1, y1, x2, y2))
684  {
685  PATH_UnlockPath(pPath);
686  return TRUE;
687  }
688 
689  ellipse[0].x = ellipse[0].y = 0;
690  ellipse[1].x = ell_width;
691  ellipse[1].y = ell_height;
692  IntLPtoDP( dc, &ellipse, 2 );
693  ell_width = min( abs( ellipse[1].x - ellipse[0].x ), corners[1].x - corners[0].x );
694  ell_height = min( abs( ellipse[1].y - ellipse[0].y ), corners[1].y - corners[0].y );
695  width = ell_width / 2.0;
696  height = ell_height / 2.0;
697 
698  /* starting point */
699  points[0].x = corners[1].x;
700  points[0].y = corners[0].y + GDI_ROUND( height );
701  /* first curve */
702  points[1].x = corners[1].x;
703  points[1].y = corners[0].y + GDI_ROUND( height * (1 - factor) );
704  points[2].x = corners[1].x - GDI_ROUND( width * (1 - factor) );
705  points[2].y = corners[0].y;
706  points[3].x = corners[1].x - GDI_ROUND( width );
707  points[3].y = corners[0].y;
708  /* horizontal line */
709  points[4].x = corners[0].x + GDI_ROUND( width );
710  points[4].y = corners[0].y;
711  /* second curve */
712  points[5].x = corners[0].x + GDI_ROUND( width * (1 - factor) );
713  points[5].y = corners[0].y;
714  points[6].x = corners[0].x;
715  points[6].y = corners[0].y + GDI_ROUND( height * (1 - factor) );
716  points[7].x = corners[0].x;
717  points[7].y = corners[0].y + GDI_ROUND( height );
718  /* vertical line */
719  points[8].x = corners[0].x;
720  points[8].y = corners[1].y - GDI_ROUND( height );
721  /* third curve */
722  points[9].x = corners[0].x;
723  points[9].y = corners[1].y - GDI_ROUND( height * (1 - factor) );
724  points[10].x = corners[0].x + GDI_ROUND( width * (1 - factor) );
725  points[10].y = corners[1].y;
726  points[11].x = corners[0].x + GDI_ROUND( width );
727  points[11].y = corners[1].y;
728  /* horizontal line */
729  points[12].x = corners[1].x - GDI_ROUND( width );
730  points[12].y = corners[1].y;
731  /* fourth curve */
732  points[13].x = corners[1].x - GDI_ROUND( width * (1 - factor) );
733  points[13].y = corners[1].y;
734  points[14].x = corners[1].x;
735  points[14].y = corners[1].y - GDI_ROUND( height * (1 - factor) );
736  points[15].x = corners[1].x;
737  points[15].y = corners[1].y - GDI_ROUND( height );
738 
739  if (dc->dclevel.flPath & DCPATH_CLOCKWISE) reverse_points( points, 16 );
740  if (!(type = add_points( pPath, points, 16, PT_BEZIERTO )))
741  {
742  PATH_UnlockPath(pPath);
743  return FALSE;
744  }
745  type[0] = PT_MOVETO;
746  type[4] = type[8] = type[12] = PT_LINETO;
747 
748  IntGdiCloseFigure(pPath);
749  PATH_UnlockPath(pPath);
750  return TRUE;
751 }
752 
753 /* PATH_Ellipse
754  *
755  */
756 BOOL
757 FASTCALL
759  PDC dc,
760  INT x1,
761  INT y1,
762  INT x2,
763  INT y2)
764 {
765  const double factor = 0.55428475; /* 4 / 3 * (sqrt(2) - 1) */
766  PPATH pPath;
767  POINT corners[2], points[13];
768  BYTE *type;
769  double width, height;
770 
771  pPath = PATH_LockPath(dc->dclevel.hPath);
772  if (!pPath) return FALSE;
773 
774  if (!PATH_CheckCorners(dc, corners, x1, y1, x2, y2))
775  {
776  PATH_UnlockPath(pPath);
777  return TRUE;
778  }
779 
780  width = (corners[1].x - corners[0].x) / 2.0;
781  height = (corners[1].y - corners[0].y) / 2.0;
782 
783  /* starting point */
784  points[0].x = corners[1].x;
785  points[0].y = corners[0].y + GDI_ROUND( height );
786  /* first curve */
787  points[1].x = corners[1].x;
788  points[1].y = corners[0].y + GDI_ROUND( height * (1 - factor) );
789  points[2].x = corners[1].x - GDI_ROUND( width * (1 - factor) );
790  points[2].y = corners[0].y;
791  points[3].x = corners[0].x + GDI_ROUND( width );
792  points[3].y = corners[0].y;
793  /* second curve */
794  points[4].x = corners[0].x + GDI_ROUND( width * (1 - factor) );
795  points[4].y = corners[0].y;
796  points[5].x = corners[0].x;
797  points[5].y = corners[0].y + GDI_ROUND( height * (1 - factor) );
798  points[6].x = corners[0].x;
799  points[6].y = corners[0].y + GDI_ROUND( height );
800  /* third curve */
801  points[7].x = corners[0].x;
802  points[7].y = corners[1].y - GDI_ROUND( height * (1 - factor) );
803  points[8].x = corners[0].x + GDI_ROUND( width * (1 - factor) );
804  points[8].y = corners[1].y;
805  points[9].x = corners[0].x + GDI_ROUND( width );
806  points[9].y = corners[1].y;
807  /* fourth curve */
808  points[10].x = corners[1].x - GDI_ROUND( width * (1 - factor) );
809  points[10].y = corners[1].y;
810  points[11].x = corners[1].x;
811  points[11].y = corners[1].y - GDI_ROUND( height * (1 - factor) );
812  points[12].x = corners[1].x;
813  points[12].y = corners[1].y - GDI_ROUND( height );
814 
815  if (dc->dclevel.flPath & DCPATH_CLOCKWISE) reverse_points( points, 13 );
816  if (!(type = add_points( pPath, points, 13, PT_BEZIERTO )))
817  {
818  DPRINT1("PATH_Ellipse No add\n");
819  PATH_UnlockPath(pPath);
820  return FALSE;
821  }
822  type[0] = PT_MOVETO;
823 
824  IntGdiCloseFigure(pPath);
825  PATH_UnlockPath(pPath);
826  return TRUE;
827 }
828 
829 /* PATH_DoArcPart
830  *
831  * Creates a Bezier spline that corresponds to part of an arc and appends the
832  * corresponding points to the path. The start and end angles are passed in
833  * "angleStart" and "angleEnd"; these angles should span a quarter circle
834  * at most. If "startEntryType" is non-zero, an entry of that type for the first
835  * control point is added to the path; otherwise, it is assumed that the current
836  * position is equal to the first control point.
837  */
838 BOOL
839 FASTCALL
841  PPATH pPath,
842  FLOAT_POINT corners[],
843  double angleStart,
844  double angleEnd,
845  BYTE startEntryType)
846 {
847  double halfAngle, a;
848  double xNorm[4], yNorm[4];
849  POINT points[4];
850  BYTE *type;
851  int i, start;
852 
853  ASSERT(fabs(angleEnd - angleStart) <= M_PI_2);
854 
855  /* FIXME: Is there an easier way of computing this? */
856 
857  /* Compute control points */
858  halfAngle = (angleEnd - angleStart) / 2.0;
859  if (fabs(halfAngle) > 1e-8)
860  {
861  a = 4.0 / 3.0 * (1 - cos(halfAngle)) / sin(halfAngle);
862  xNorm[0] = cos(angleStart);
863  yNorm[0] = sin(angleStart);
864  xNorm[1] = xNorm[0] - a * yNorm[0];
865  yNorm[1] = yNorm[0] + a * xNorm[0];
866  xNorm[3] = cos(angleEnd);
867  yNorm[3] = sin(angleEnd);
868  xNorm[2] = xNorm[3] + a * yNorm[3];
869  yNorm[2] = yNorm[3] - a * xNorm[3];
870  }
871  else
872  for (i = 0; i < 4; i++)
873  {
874  xNorm[i] = cos(angleStart);
875  yNorm[i] = sin(angleStart);
876  }
877 
878  /* Add starting point to path if desired */
879  start = !startEntryType;
880 
881  /* Add remaining control points */
882  for (i = start; i < 4; i++) PATH_ScaleNormalizedPoint(corners, xNorm[i], yNorm[i], &points[i]);
883  if (!(type = add_points( pPath, points + start, 4 - start, PT_BEZIERTO ))) return FALSE;
884  if (!start) type[0] = startEntryType;
885 
886  return TRUE;
887 }
888 
889 /* PATH_Arc
890  *
891  * Should be called when a call to Arc is performed on a DC that has
892  * an open path. This adds up to five Bezier splines representing the arc
893  * to the path. When 'lines' is 1, we add 1 extra line to get a chord,
894  * when 'lines' is 2, we add 2 extra lines to get a pie, and when 'lines' is
895  * -1 we add 1 extra line from the current DC position to the starting position
896  * of the arc before drawing the arc itself (arcto). Returns TRUE if successful,
897  * else FALSE.
898  */
899 BOOL
900 FASTCALL
902  PDC dc,
903  INT x1,
904  INT y1,
905  INT x2,
906  INT y2,
907  INT xStart,
908  INT yStart,
909  INT xEnd,
910  INT yEnd,
911  INT direction,
912  INT lines)
913 {
914  double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant = 0.0;
915  /* Initialize angleEndQuadrant to silence gcc's warning */
916  double x, y;
917  FLOAT_POINT corners[2], pointStart, pointEnd;
918  POINT centre, pointCurPos;
919  BOOL start, end, Ret = TRUE;
920  INT temp;
921  BOOL clockwise;
922  PPATH pPath;
923 
924  /* FIXME: This function should check for all possible error returns */
925  /* FIXME: Do we have to respect newStroke? */
926 
927  ASSERT(dc);
928 
929  pPath = PATH_LockPath(dc->dclevel.hPath);
930  if (!pPath) return FALSE;
931 
932  if (direction)
933  clockwise = ((direction == AD_CLOCKWISE) !=0 );
934  else
935  clockwise = ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
936 
937  /* Check for zero height / width */
938  /* FIXME: Only in GM_COMPATIBLE? */
939  if (x1 == x2 || y1 == y2)
940  {
941  Ret = TRUE;
942  goto ArcExit;
943  }
944  /* Convert points to device coordinates */
945  corners[0].x = (FLOAT)x1;
946  corners[0].y = (FLOAT)y1;
947  corners[1].x = (FLOAT)x2;
948  corners[1].y = (FLOAT)y2;
949  pointStart.x = (FLOAT)xStart;
950  pointStart.y = (FLOAT)yStart;
951  pointEnd.x = (FLOAT)xEnd;
952  pointEnd.y = (FLOAT)yEnd;
953  INTERNAL_LPTODP_FLOAT(dc, corners);
954  INTERNAL_LPTODP_FLOAT(dc, corners + 1);
955  INTERNAL_LPTODP_FLOAT(dc, &pointStart);
956  INTERNAL_LPTODP_FLOAT(dc, &pointEnd);
957 
958  /* Make sure first corner is top left and second corner is bottom right */
959  if (corners[0].x > corners[1].x)
960  {
961  temp = corners[0].x;
962  corners[0].x = corners[1].x;
963  corners[1].x = temp;
964  }
965  if (corners[0].y > corners[1].y)
966  {
967  temp = corners[0].y;
968  corners[0].y = corners[1].y;
969  corners[1].y = temp;
970  }
971 
972  /* Compute start and end angle */
973  PATH_NormalizePoint(corners, &pointStart, &x, &y);
974  angleStart = atan2(y, x);
975  PATH_NormalizePoint(corners, &pointEnd, &x, &y);
976  angleEnd = atan2(y, x);
977 
978  /* Make sure the end angle is "on the right side" of the start angle */
979  if (clockwise)
980  {
981  if (angleEnd <= angleStart)
982  {
983  angleEnd += 2 * M_PI;
984  ASSERT(angleEnd >= angleStart);
985  }
986  }
987  else
988  {
989  if (angleEnd >= angleStart)
990  {
991  angleEnd -= 2 * M_PI;
992  ASSERT(angleEnd <= angleStart);
993  }
994  }
995 
996  /* In GM_COMPATIBLE, don't include bottom and right edges */
997  if (dc->pdcattr->iGraphicsMode == GM_COMPATIBLE)
998  {
999  corners[1].x--;
1000  corners[1].y--;
1001  }
1002 
1003  /* arcto: Add a PT_MOVETO only if this is the first entry in a stroke */
1004  if (lines == GdiTypeArcTo && pPath->newStroke) // -1
1005  {
1006  pPath->newStroke = FALSE;
1007  IntGetCurrentPositionEx(dc, &pointCurPos);
1008  CoordLPtoDP(dc, &pointCurPos);
1009  if (!PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO))
1010  {
1011  Ret = FALSE;
1012  goto ArcExit;
1013  }
1014  }
1015 
1016  /* Add the arc to the path with one Bezier spline per quadrant that the
1017  * arc spans */
1018  start = TRUE;
1019  end = FALSE;
1020  do
1021  {
1022  /* Determine the start and end angles for this quadrant */
1023  if (start)
1024  {
1025  angleStartQuadrant = angleStart;
1026  if (clockwise)
1027  angleEndQuadrant = (floor(angleStart / M_PI_2) + 1.0) * M_PI_2;
1028  else
1029  angleEndQuadrant = (ceil(angleStart / M_PI_2) - 1.0) * M_PI_2;
1030  }
1031  else
1032  {
1033  angleStartQuadrant = angleEndQuadrant;
1034  if (clockwise)
1035  angleEndQuadrant += M_PI_2;
1036  else
1037  angleEndQuadrant -= M_PI_2;
1038  }
1039 
1040  /* Have we reached the last part of the arc? */
1041  if ((clockwise && angleEnd < angleEndQuadrant) ||
1042  (!clockwise && angleEnd > angleEndQuadrant))
1043  {
1044  /* Adjust the end angle for this quadrant */
1045  angleEndQuadrant = angleEnd;
1046  end = TRUE;
1047  }
1048 
1049  /* Add the Bezier spline to the path */
1050  PATH_DoArcPart(pPath,
1051  corners,
1052  angleStartQuadrant,
1053  angleEndQuadrant,
1054  start ? (lines == GdiTypeArcTo ? PT_LINETO : PT_MOVETO) : FALSE); // -1
1055  start = FALSE;
1056  }
1057  while (!end);
1058 
1059  if (lines == GdiTypeArcTo)
1060  {
1061  update_current_pos( pPath );
1062  }
1063  else /* chord: close figure. pie: add line and close figure */
1064  if (lines == GdiTypeChord) // 1
1065  {
1066  IntGdiCloseFigure(pPath);
1067  }
1068  else if (lines == GdiTypePie) // 2
1069  {
1070  centre.x = (corners[0].x + corners[1].x) / 2;
1071  centre.y = (corners[0].y + corners[1].y) / 2;
1072  if (!PATH_AddEntry(pPath, &centre, PT_LINETO | PT_CLOSEFIGURE))
1073  Ret = FALSE;
1074  }
1075 ArcExit:
1076  PATH_UnlockPath(pPath);
1077  return Ret;
1078 }
1079 
1080 BOOL
1081 FASTCALL
1083  PDC dc,
1084  const POINT *pts,
1085  DWORD cbPoints)
1086 {
1087  PPATH pPath;
1088  BOOL ret;
1089 
1090  ASSERT(dc);
1091  ASSERT(pts);
1092  ASSERT(cbPoints);
1093 
1094  pPath = PATH_LockPath(dc->dclevel.hPath);
1095  if (!pPath) return FALSE;
1096 
1097  ret = add_log_points_new_stroke( dc, pPath, pts, cbPoints, PT_BEZIERTO );
1098 
1099  PATH_UnlockPath(pPath);
1100  return ret;
1101 }
1102 
1103 BOOL
1104 FASTCALL
1106  PDC dc,
1107  const POINT *pts,
1108  DWORD cbPoints)
1109 {
1110  PPATH pPath;
1111  BYTE *type;
1112 
1113  ASSERT(dc);
1114  ASSERT(pts);
1115  ASSERT(cbPoints);
1116 
1117  pPath = PATH_LockPath(dc->dclevel.hPath);
1118  if (!pPath) return FALSE;
1119 
1120  type = add_log_points( dc, pPath, pts, cbPoints, PT_BEZIERTO );
1121  if (!type) return FALSE;
1122 
1123  type[0] = PT_MOVETO;
1124 
1125  PATH_UnlockPath(pPath);
1126  return TRUE;
1127 }
1128 
1129 BOOL
1130 FASTCALL
1132  PDC dc,
1133  const POINT *pts,
1134  const BYTE *types,
1135  DWORD cbPoints)
1136 {
1137  PPATH pPath;
1138  POINT orig_pos, cur_pos;
1139  ULONG i, lastmove = 0;
1140 
1141  pPath = PATH_LockPath(dc->dclevel.hPath);
1142  if (!pPath) return FALSE;
1143 
1144  if (pPath->state != PATH_Open)
1145  {
1146  PATH_UnlockPath(pPath);
1147  return FALSE;
1148  }
1149 
1150  for (i = 0; i < pPath->numEntriesUsed; i++) if (pPath->pFlags[i] == PT_MOVETO) lastmove = i;
1151  orig_pos = pPath->pos;
1152 
1153  IntGetCurrentPositionEx(dc, &cur_pos);
1154 
1155  DPRINT("PPD : Current pos X %d Y %d\n",pPath->pos.x, pPath->pos.y);
1156  DPRINT("PPD : last %d pos X %d Y %d\n",lastmove, pPath->pPoints[lastmove].x, pPath->pPoints[lastmove].y);
1157 
1158 
1159  for(i = 0; i < cbPoints; i++)
1160  {
1161  switch (types[i])
1162  {
1163  case PT_MOVETO:
1164  pPath->newStroke = TRUE;
1165  pPath->pos = pts[i];
1166  IntLPtoDP( dc, &pPath->pos, 1);
1167  lastmove = pPath->numEntriesUsed;
1168  break;
1169  case PT_LINETO:
1170  case PT_LINETO | PT_CLOSEFIGURE:
1171  if (!add_log_points_new_stroke( dc, pPath, &pts[i], 1, PT_LINETO ))
1172  {
1173  PATH_UnlockPath(pPath);
1174  return FALSE;
1175  }
1176  break;
1177  case PT_BEZIERTO:
1178  if ((i + 2 < cbPoints) && (types[i + 1] == PT_BEZIERTO) &&
1179  (types[i + 2] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
1180  {
1181  if (!add_log_points_new_stroke( dc, pPath, &pts[i], 3, PT_BEZIERTO ))
1182  {
1183  PATH_UnlockPath(pPath);
1184  return FALSE;
1185  }
1186  i += 2;
1187  break;
1188  }
1189  /* fall through */
1190  default:
1191  /* restore original position */
1192  pPath->pos = orig_pos;
1193 
1194  DPRINT("PPD Bad : pos X %d Y %d\n",pPath->pos.x, pPath->pos.y);
1195 
1196  IntGdiMoveToEx(dc, cur_pos.x, cur_pos.y, NULL);
1197 
1198  PATH_UnlockPath(pPath);
1199  return FALSE;
1200  }
1201 
1202  if (types[i] & PT_CLOSEFIGURE)
1203  {
1204  close_figure( pPath );
1205  pPath->pos = pPath->pPoints[lastmove];
1206  DPRINT("PPD close : pos X %d Y %d\n",pPath->pos.x, pPath->pos.y);
1207  }
1208  }
1209  PATH_UnlockPath(pPath);
1210  return TRUE;
1211 }
1212 
1213 BOOL
1214 FASTCALL
1216  PDC dc,
1217  const POINT *pts,
1218  DWORD cbPoints)
1219 {
1220  PPATH pPath;
1221  BOOL ret;
1222 
1223  ASSERT(dc);
1224  ASSERT(pts);
1225  ASSERT(cbPoints);
1226 
1227  if (cbPoints < 1) return FALSE;
1228 
1229  pPath = PATH_LockPath(dc->dclevel.hPath);
1230  if (!pPath) return FALSE;
1231 
1232  ret = add_log_points_new_stroke( dc, pPath, pts, cbPoints, PT_LINETO );
1233  PATH_UnlockPath(pPath);
1234  return ret;
1235 }
1236 
1237 BOOL
1238 FASTCALL
1240  PDC dc,
1241  const POINT* pts,
1242  const INT* counts,
1243  UINT polygons)
1244 {
1245  UINT poly, count;
1246  BYTE *type;
1247  PPATH pPath;
1248 
1249  ASSERT(dc);
1250  ASSERT(pts);
1251  ASSERT(counts);
1252  ASSERT(polygons);
1253 
1254  if (!polygons) return FALSE;
1255 
1256  pPath = PATH_LockPath(dc->dclevel.hPath);
1257  if (!pPath) return FALSE;
1258 
1259 
1260  for (poly = count = 0; poly < polygons; poly++)
1261  {
1262  if (counts[poly] < 2)
1263  {
1264  PATH_UnlockPath(pPath);
1265  return FALSE;
1266  }
1267  count += counts[poly];
1268  }
1269 
1270  type = add_log_points( dc, pPath, pts, count, PT_LINETO );
1271  if (!type)
1272  {
1273  PATH_UnlockPath(pPath);
1274  return FALSE;
1275  }
1276 
1277  /* make the first point of each polyline a PT_MOVETO, and close the last one */
1278  for (poly = 0; poly < polygons; type += counts[poly++])
1279  {
1280  type[0] = PT_MOVETO;
1281  type[counts[poly] - 1] = PT_LINETO | PT_CLOSEFIGURE;
1282  }
1283  PATH_UnlockPath(pPath);
1284  return TRUE;
1285 }
1286 
1287 BOOL
1288 FASTCALL
1290  PDC dc,
1291  const POINT* pts,
1292  const DWORD* counts,
1293  DWORD polylines)
1294 {
1295  POINT pt;
1296  ULONG poly, point, i;
1297  PPATH pPath;
1298 
1299  ASSERT(dc);
1300  ASSERT(pts);
1301  ASSERT(counts);
1302  ASSERT(polylines);
1303 
1304  pPath = PATH_LockPath(dc->dclevel.hPath);
1305  if (!pPath)
1306  {
1307  return FALSE;
1308  }
1309 
1310  for (i = 0, poly = 0; poly < polylines; poly++)
1311  {
1312  for (point = 0; point < counts[poly]; point++, i++)
1313  {
1314  pt = pts[i];
1315  CoordLPtoDP(dc, &pt);
1316  PATH_AddEntry(pPath, &pt, (point == 0) ? PT_MOVETO : PT_LINETO);
1317  }
1318  }
1319  DPRINT("PATH_PolyPolyline end count %d\n",pPath->numEntriesUsed);
1320  PATH_UnlockPath(pPath);
1321  return TRUE;
1322 }
1323 
1324 /* PATH_AddFlatBezier
1325  *
1326  */
1327 BOOL
1328 FASTCALL
1330  PPATH pPath,
1331  POINT *pt,
1332  BOOL closed)
1333 {
1334  POINT *pts;
1335  BOOL ret = FALSE;
1336  INT no, i;
1337 
1338  pts = GDI_Bezier(pt, 4, &no);
1339  if (!pts) return FALSE;
1340 
1341  for (i = 1; i < no; i++)
1342  {
1343  if (!(ret = PATH_AddEntry(pPath, &pts[i], (i == no - 1 && closed) ? PT_LINETO | PT_CLOSEFIGURE : PT_LINETO)))
1344  break;
1345  }
1346 
1348  return ret;
1349 }
1350 
1351 /* PATH_FlattenPath
1352  *
1353  * Replaces Beziers with line segments
1354  *
1355  */
1356 PPATH
1357 FASTCALL
1359 {
1360  PPATH newPath;
1361  INT srcpt;
1362  DPRINT("PATH_FlattenPath\n");
1363  if (!(newPath = PATH_CreatePath(pPath->numEntriesUsed))) return NULL;
1364 
1365  for (srcpt = 0; srcpt < pPath->numEntriesUsed; srcpt++)
1366  {
1367  switch(pPath->pFlags[srcpt] & ~PT_CLOSEFIGURE)
1368  {
1369  case PT_MOVETO:
1370  case PT_LINETO:
1371  if (!PATH_AddEntry(newPath, &pPath->pPoints[srcpt], pPath->pFlags[srcpt]))
1372  {
1373  PATH_UnlockPath(newPath);
1374  PATH_Delete(newPath->BaseObject.hHmgr);
1375  return NULL;
1376  }
1377  break;
1378  case PT_BEZIERTO:
1379  if(!PATH_AddFlatBezier(newPath, &pPath->pPoints[srcpt - 1], pPath->pFlags[srcpt + 2] & PT_CLOSEFIGURE))
1380  {
1381  PATH_UnlockPath(newPath);
1382  PATH_Delete(newPath->BaseObject.hHmgr);
1383  return NULL;
1384  }
1385  srcpt += 2;
1386  break;
1387  }
1388  }
1389  DPRINT("PATH_FlattenPath good\n");
1390  newPath->state = pPath->state;
1391  return newPath;
1392 }
1393 
1394 /* PATH_PathToRegion
1395  *
1396  * Creates a region from the specified path using the specified polygon
1397  * filling mode. The path is left unchanged. A handle to the region that
1398  * was created is stored in *pHrgn.
1399  */
1400 BOOL
1401 FASTCALL
1403  PPATH pPath,
1404  INT Mode,
1405  PREGION Rgn)
1406 {
1407  int i, pos, polygons;
1408  PULONG counts;
1409  int Ret;
1410 
1411  if (!pPath->numEntriesUsed) return FALSE;
1412 
1413  counts = ExAllocatePoolWithTag(PagedPool, (pPath->numEntriesUsed / 2) * sizeof(counts), TAG_PATH);
1414  if (!counts)
1415  {
1416  DPRINT1("Failed to allocate %lu strokes\n", (pPath->numEntriesUsed / 2) * sizeof(*counts));
1418  return FALSE;
1419  }
1420 
1421  pos = polygons = 0;
1422  ASSERT( pPath->pFlags[0] == PT_MOVETO );
1423  for (i = 1; i < pPath->numEntriesUsed; i++)
1424  {
1425  if (pPath->pFlags[i] != PT_MOVETO) continue;
1426  counts[polygons++] = i - pos;
1427  pos = i;
1428  }
1429  if (i > pos + 1) counts[polygons++] = i - pos;
1430 
1431  ASSERT( polygons <= pPath->numEntriesUsed / 2 );
1432 
1433  /* Fill the region with the strokes */
1434  Ret = REGION_SetPolyPolygonRgn(Rgn,
1435  pPath->pPoints,
1436  counts,
1437  polygons,
1438  Mode);
1439  if (!Ret)
1440  {
1441  DPRINT1("REGION_SetPolyPolygonRgn failed\n");
1442  }
1443 
1444  ExFreePoolWithTag(counts, TAG_PATH);
1445 
1446  /* Success! */
1447  return Ret;
1448 }
1449 
1450 /* PATH_FillPath
1451  *
1452  * You can play with this as long as you like, but if you break Area.exe the purge will Begain on Path!!!
1453  *
1454  */
1455 BOOL
1456 FASTCALL
1458  PDC dc,
1459  PPATH pPath)
1460 {
1461  INT mapMode, graphicsMode;
1462  SIZE ptViewportExt, ptWindowExt;
1463  POINTL ptViewportOrg, ptWindowOrg;
1464  XFORML xform;
1465  PREGION Rgn;
1466  PDC_ATTR pdcattr = dc->pdcattr;
1467 
1468  /* Allocate a temporary region */
1469  Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
1470  if (!Rgn)
1471  {
1473  return FALSE;
1474  }
1475 
1476  if (!PATH_PathToRegion(pPath, pdcattr->jFillMode, Rgn))
1477  {
1478  DPRINT("PFP : Fail P2R\n");
1479  /* EngSetLastError ? */
1480  REGION_Delete(Rgn);
1481  return FALSE;
1482  }
1483 
1484  /* Since PaintRgn interprets the region as being in logical coordinates
1485  * but the points we store for the path are already in device
1486  * coordinates, we have to set the mapping mode to MM_TEXT temporarily.
1487  * Using SaveDC to save information about the mapping mode / world
1488  * transform would be easier but would require more overhead, especially
1489  * now that SaveDC saves the current path.
1490  */
1491 
1492  /* Save the information about the old mapping mode */
1493  mapMode = pdcattr->iMapMode;
1494  ptViewportExt = pdcattr->szlViewportExt;
1495  ptViewportOrg = pdcattr->ptlViewportOrg;
1496  ptWindowExt = pdcattr->szlWindowExt;
1497  ptWindowOrg = pdcattr->ptlWindowOrg;
1498 
1499  /* Save world transform
1500  * NB: The Windows documentation on world transforms would lead one to
1501  * believe that this has to be done only in GM_ADVANCED; however, my
1502  * tests show that resetting the graphics mode to GM_COMPATIBLE does
1503  * not reset the world transform.
1504  */
1505  MatrixS2XForm(&xform, &dc->pdcattr->mxWorldToPage);
1506 
1507  /* Set MM_TEXT */
1509  pdcattr->ptlViewportOrg.x = 0;
1510  pdcattr->ptlViewportOrg.y = 0;
1511  pdcattr->ptlWindowOrg.x = 0;
1512  pdcattr->ptlWindowOrg.y = 0;
1513 
1514  graphicsMode = pdcattr->iGraphicsMode;
1515  pdcattr->iGraphicsMode = GM_ADVANCED;
1517  pdcattr->iGraphicsMode = graphicsMode;
1518 
1519  /* Paint the region */
1520  IntGdiPaintRgn(dc, Rgn);
1521  REGION_Delete(Rgn);
1522  /* Restore the old mapping mode */
1523  IntGdiSetMapMode(dc, mapMode);
1524  pdcattr->szlViewportExt = ptViewportExt;
1525  pdcattr->ptlViewportOrg = ptViewportOrg;
1526  pdcattr->szlWindowExt = ptWindowExt;
1527  pdcattr->ptlWindowOrg = ptWindowOrg;
1528 
1529  /* Go to GM_ADVANCED temporarily to restore the world transform */
1530  graphicsMode = pdcattr->iGraphicsMode;
1531  pdcattr->iGraphicsMode = GM_ADVANCED;
1532  GreModifyWorldTransform(dc, &xform, MWT_MAX+1);
1533  pdcattr->iGraphicsMode = graphicsMode;
1534  return TRUE;
1535 }
1536 
1537 BOOL
1538 FASTCALL
1540  DC *dc,
1541  PPATH pPath)
1542 {
1543  BOOL ret = FALSE;
1544  INT i = 0;
1545  INT nLinePts, nAlloc;
1546  POINT *pLinePts = NULL;
1547  POINT ptViewportOrg, ptWindowOrg;
1548  SIZE szViewportExt, szWindowExt;
1549  DWORD mapMode, graphicsMode;
1550  XFORM xform;
1551  PDC_ATTR pdcattr = dc->pdcattr;
1552 
1553  DPRINT("Enter %s\n", __FUNCTION__);
1554 
1555  /* Save the mapping mode info */
1556  mapMode = pdcattr->iMapMode;
1557 
1558  szViewportExt = *DC_pszlViewportExt(dc);
1559  ptViewportOrg = dc->pdcattr->ptlViewportOrg;
1560  szWindowExt = dc->pdcattr->szlWindowExt;
1561  ptWindowOrg = dc->pdcattr->ptlWindowOrg;
1562 
1563  MatrixS2XForm(&xform, &dc->pdcattr->mxWorldToPage);
1564 
1565  /* Set MM_TEXT */
1566  pdcattr->iMapMode = MM_TEXT;
1567  pdcattr->ptlViewportOrg.x = 0;
1568  pdcattr->ptlViewportOrg.y = 0;
1569  pdcattr->ptlWindowOrg.x = 0;
1570  pdcattr->ptlWindowOrg.y = 0;
1571  graphicsMode = pdcattr->iGraphicsMode;
1572  pdcattr->iGraphicsMode = GM_ADVANCED;
1574  pdcattr->iGraphicsMode = graphicsMode;
1575 
1576  /* Allocate enough memory for the worst case without beziers (one PT_MOVETO
1577  * and the rest PT_LINETO with PT_CLOSEFIGURE at the end) plus some buffer
1578  * space in case we get one to keep the number of reallocations small. */
1579  nAlloc = pPath->numEntriesUsed + 1 + 300;
1580  pLinePts = ExAllocatePoolWithTag(PagedPool, nAlloc * sizeof(POINT), TAG_PATH);
1581  if (!pLinePts)
1582  {
1583  DPRINT1("Can't allocate pool!\n");
1585  goto end;
1586  }
1587  nLinePts = 0;
1588 
1589  for (i = 0; i < pPath->numEntriesUsed; i++)
1590  {
1591  if ((i == 0 || (pPath->pFlags[i - 1] & PT_CLOSEFIGURE))
1592  && (pPath->pFlags[i] != PT_MOVETO))
1593  {
1594  DPRINT1("Expected PT_MOVETO %s, got path flag %d\n",
1595  i == 0 ? "as first point" : "after PT_CLOSEFIGURE",
1596  (INT)pPath->pFlags[i]);
1597  goto end;
1598  }
1599 
1600  switch(pPath->pFlags[i])
1601  {
1602  case PT_MOVETO:
1603  DPRINT("Got PT_MOVETO (%ld, %ld)\n",
1604  pPath->pPoints[i].x, pPath->pPoints[i].y);
1605  if (nLinePts >= 2) IntGdiPolyline(dc, pLinePts, nLinePts);
1606  nLinePts = 0;
1607  pLinePts[nLinePts++] = pPath->pPoints[i];
1608  break;
1609  case PT_LINETO:
1610  case (PT_LINETO | PT_CLOSEFIGURE):
1611  DPRINT("Got PT_LINETO (%ld, %ld)\n",
1612  pPath->pPoints[i].x, pPath->pPoints[i].y);
1613  pLinePts[nLinePts++] = pPath->pPoints[i];
1614  break;
1615  case PT_BEZIERTO:
1616  DPRINT("Got PT_BEZIERTO\n");
1617  if (pPath->pFlags[i + 1] != PT_BEZIERTO ||
1618  (pPath->pFlags[i + 2] & ~PT_CLOSEFIGURE) != PT_BEZIERTO)
1619  {
1620  DPRINT1("Path didn't contain 3 successive PT_BEZIERTOs\n");
1621  ret = FALSE;
1622  goto end;
1623  }
1624  else
1625  {
1626  INT nBzrPts, nMinAlloc;
1627  POINT *pBzrPts = GDI_Bezier(&pPath->pPoints[i - 1], 4, &nBzrPts);
1628  /* Make sure we have allocated enough memory for the lines of
1629  * this bezier and the rest of the path, assuming we won't get
1630  * another one (since we won't reallocate again then). */
1631  nMinAlloc = nLinePts + (pPath->numEntriesUsed - i) + nBzrPts;
1632  if (nAlloc < nMinAlloc)
1633  {
1634  // Reallocate memory
1635 
1636  POINT *Realloc = NULL;
1637  nAlloc = nMinAlloc * 2;
1638 
1639  Realloc = ExAllocatePoolWithTag(PagedPool,
1640  nAlloc * sizeof(POINT),
1641  TAG_PATH);
1642 
1643  if (!Realloc)
1644  {
1645  DPRINT1("Can't allocate pool!\n");
1646  ExFreePoolWithTag(pBzrPts, TAG_BEZIER);
1647  goto end;
1648  }
1649 
1650  memcpy(Realloc, pLinePts, nLinePts * sizeof(POINT));
1651  ExFreePoolWithTag(pLinePts, TAG_PATH);
1652  pLinePts = Realloc;
1653  }
1654  memcpy(&pLinePts[nLinePts], &pBzrPts[1], (nBzrPts - 1) * sizeof(POINT));
1655  nLinePts += nBzrPts - 1;
1656  ExFreePoolWithTag(pBzrPts, TAG_BEZIER);
1657  i += 2;
1658  }
1659  break;
1660  default:
1661  DPRINT1("Got path flag %d (not supported)\n", (INT)pPath->pFlags[i]);
1662  goto end;
1663  }
1664 
1665  if (pPath->pFlags[i] & PT_CLOSEFIGURE)
1666  {
1667  pLinePts[nLinePts++] = pLinePts[0];
1668  }
1669  }
1670  if (nLinePts >= 2)
1671  IntGdiPolyline(dc, pLinePts, nLinePts);
1672 
1673  ret = TRUE;
1674 
1675 end:
1676  if (pLinePts) ExFreePoolWithTag(pLinePts, TAG_PATH);
1677 
1678  /* Restore the old mapping mode */
1679  pdcattr->iMapMode = mapMode;
1680  pdcattr->szlWindowExt.cx = szWindowExt.cx;
1681  pdcattr->szlWindowExt.cy = szWindowExt.cy;
1682  pdcattr->ptlWindowOrg.x = ptWindowOrg.x;
1683  pdcattr->ptlWindowOrg.y = ptWindowOrg.y;
1684 
1685  pdcattr->szlViewportExt.cx = szViewportExt.cx;
1686  pdcattr->szlViewportExt.cy = szViewportExt.cy;
1687  pdcattr->ptlViewportOrg.x = ptViewportOrg.x;
1688  pdcattr->ptlViewportOrg.y = ptViewportOrg.y;
1689 
1690  /* Restore the world transform */
1691  XForm2MatrixS(&dc->pdcattr->mxWorldToPage, &xform);
1692 
1693  /* If we've moved the current point then get its new position
1694  which will be in device (MM_TEXT) co-ords, convert it to
1695  logical co-ords and re-set it. This basically updates
1696  dc->CurPosX|Y so that their values are in the correct mapping
1697  mode.
1698  */
1699  if (i > 0)
1700  {
1701  POINT pt;
1702  IntGetCurrentPositionEx(dc, &pt);
1703  IntDPtoLP(dc, &pt, 1);
1704  IntGdiMoveToEx(dc, pt.x, pt.y, NULL);
1705  }
1706  DPRINT("Leave %s, ret=%d\n", __FUNCTION__, ret);
1707  return ret;
1708 }
1709 
1710 #define round(x) ((int)((x)>0?(x)+0.5:(x)-0.5))
1711 
1712 static
1713 PPATH
1714 FASTCALL
1716 {
1717  INT i, j, numStrokes, numOldStrokes, penWidth, penWidthIn, penWidthOut, size, penStyle;
1718  PPATH pPath, flat_path, pNewPath, *pStrokes = NULL, *pOldStrokes, pUpPath, pDownPath;
1719  EXTLOGPEN *elp;
1720  BYTE *type;
1721  DWORD obj_type, joint, endcap, penType;
1722  PDC_ATTR pdcattr = dc->pdcattr;
1723 
1724  pPath = PATH_LockPath(dc->dclevel.hPath);
1725  if (!pPath)
1726  {
1728  return NULL;
1729  }
1730 
1731  if (pPath->state != PATH_Closed)
1732  {
1733  DPRINT("PWP 1\n");
1734  PATH_UnlockPath(pPath);
1736  return NULL;
1737  }
1738 
1739  size = GreGetObject(pdcattr->hpen, 0, NULL);
1740  if (!size)
1741  {
1742  DPRINT("PWP 2\n");
1743  PATH_UnlockPath(pPath);
1745  return FALSE;
1746  }
1747 
1749  if (elp == NULL)
1750  {
1751  DPRINT("PWP 3\n");
1752  PATH_UnlockPath(pPath);
1754  return FALSE;
1755  }
1756 
1757  GreGetObject(pdcattr->hpen, size, elp);
1758 
1759  obj_type = GDI_HANDLE_GET_TYPE(pdcattr->hpen);
1760  if (obj_type == GDI_OBJECT_TYPE_PEN)
1761  {
1762  penStyle = ((LOGPEN*)elp)->lopnStyle;
1763  }
1764  else if (obj_type == GDI_OBJECT_TYPE_EXTPEN)
1765  {
1766  penStyle = elp->elpPenStyle;
1767  }
1768  else
1769  {
1770  DPRINT("PWP 4\n");
1773  PATH_UnlockPath(pPath);
1774  return FALSE;
1775  }
1776 
1777  penWidth = elp->elpWidth;
1779 
1780  endcap = (PS_ENDCAP_MASK & penStyle);
1781  joint = (PS_JOIN_MASK & penStyle);
1782  penType = (PS_TYPE_MASK & penStyle);
1783 
1784  /* The function cannot apply to cosmetic pens */
1785  if (obj_type == GDI_OBJECT_TYPE_EXTPEN && penType == PS_COSMETIC)
1786  {
1787  DPRINT("PWP 5\n");
1788  PATH_UnlockPath(pPath);
1790  return FALSE;
1791  }
1792 
1793  if (!(flat_path = PATH_FlattenPath(pPath)))
1794  {
1795  PATH_UnlockPath(pPath);
1796  return NULL;
1797  }
1798  PATH_UnlockPath(pPath);
1799 
1800  penWidthIn = penWidth / 2;
1801  penWidthOut = penWidth / 2;
1802  if (penWidthIn + penWidthOut < penWidth)
1803  penWidthOut++;
1804 
1805  numStrokes = 0;
1806 
1807  for (i = 0, j = 0; i < flat_path->numEntriesUsed; i++, j++)
1808  {
1809  POINT point;
1810  if ((i == 0 || (flat_path->pFlags[i - 1] & PT_CLOSEFIGURE)) &&
1811  (flat_path->pFlags[i] != PT_MOVETO))
1812  {
1813  DPRINT1("Expected PT_MOVETO %s, got path flag %c\n",
1814  i == 0 ? "as first point" : "after PT_CLOSEFIGURE",
1815  flat_path->pFlags[i]);
1816  if (pStrokes)
1817  ExFreePoolWithTag(pStrokes, TAG_PATH);
1818  PATH_UnlockPath(flat_path);
1819  PATH_Delete(flat_path->BaseObject.hHmgr);
1820  return FALSE;
1821  }
1822  switch(flat_path->pFlags[i])
1823  {
1824  case PT_MOVETO:
1825  if (numStrokes > 0)
1826  {
1827  pStrokes[numStrokes - 1]->state = PATH_Closed;
1828  }
1829  numOldStrokes = numStrokes;
1830  numStrokes++;
1831  j = 0;
1832  if (numStrokes == 1)
1833  pStrokes = ExAllocatePoolWithTag(PagedPool, sizeof(*pStrokes), TAG_PATH);
1834  else
1835  {
1836  pOldStrokes = pStrokes; // Save old pointer.
1837  pStrokes = ExAllocatePoolWithTag(PagedPool, numStrokes * sizeof(*pStrokes), TAG_PATH);
1838  if (!pStrokes)
1839  {
1840  PATH_UnlockPath(flat_path);
1841  PATH_Delete(flat_path->BaseObject.hHmgr);
1842  return FALSE;
1843  }
1844  RtlCopyMemory(pStrokes, pOldStrokes, numOldStrokes * sizeof(PPATH));
1845  ExFreePoolWithTag(pOldStrokes, TAG_PATH); // Free old pointer.
1846  }
1847  if (!pStrokes)
1848  {
1849  PATH_UnlockPath(flat_path);
1850  PATH_Delete(flat_path->BaseObject.hHmgr);
1851  return FALSE;
1852  }
1853  pStrokes[numStrokes - 1] = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
1854  if (!pStrokes[numStrokes - 1])
1855  {
1856  ASSERT(FALSE); // FIXME
1857  }
1858  PATH_InitGdiPath(pStrokes[numStrokes - 1]);
1859  pStrokes[numStrokes - 1]->state = PATH_Open;
1860  case PT_LINETO:
1861  case (PT_LINETO | PT_CLOSEFIGURE):
1862  point.x = flat_path->pPoints[i].x;
1863  point.y = flat_path->pPoints[i].y;
1864  PATH_AddEntry(pStrokes[numStrokes - 1], &point, flat_path->pFlags[i]);
1865  break;
1866  case PT_BEZIERTO:
1867  /* Should never happen because of the FlattenPath call */
1868  DPRINT1("Should never happen\n");
1869  break;
1870  default:
1871  DPRINT1("Got path flag %c\n", flat_path->pFlags[i]);
1872  if (pStrokes)
1873  ExFreePoolWithTag(pStrokes, TAG_PATH);
1874  PATH_UnlockPath(flat_path);
1875  PATH_Delete(flat_path->BaseObject.hHmgr);
1876  return FALSE;
1877  }
1878  }
1879 
1880  pNewPath = PATH_CreatePath( flat_path->numEntriesUsed );
1881 
1882  for (i = 0; i < numStrokes; i++)
1883  {
1884  pUpPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
1885  PATH_InitGdiPath(pUpPath);
1886  pUpPath->state = PATH_Open;
1887  pDownPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
1888  PATH_InitGdiPath(pDownPath);
1889  pDownPath->state = PATH_Open;
1890 
1891  for (j = 0; j < pStrokes[i]->numEntriesUsed; j++)
1892  {
1893  /* Beginning or end of the path if not closed */
1894  if ((!(pStrokes[i]->pFlags[pStrokes[i]->numEntriesUsed - 1] & PT_CLOSEFIGURE)) && (j == 0 || j == pStrokes[i]->numEntriesUsed - 1))
1895  {
1896  /* Compute segment angle */
1897  double xo, yo, xa, ya, theta;
1898  POINT pt;
1899  FLOAT_POINT corners[2];
1900  if (j == 0)
1901  {
1902  xo = pStrokes[i]->pPoints[j].x;
1903  yo = pStrokes[i]->pPoints[j].y;
1904  xa = pStrokes[i]->pPoints[1].x;
1905  ya = pStrokes[i]->pPoints[1].y;
1906  }
1907  else
1908  {
1909  xa = pStrokes[i]->pPoints[j - 1].x;
1910  ya = pStrokes[i]->pPoints[j - 1].y;
1911  xo = pStrokes[i]->pPoints[j].x;
1912  yo = pStrokes[i]->pPoints[j].y;
1913  }
1914  theta = atan2(ya - yo, xa - xo);
1915  switch(endcap)
1916  {
1917  case PS_ENDCAP_SQUARE :
1918  pt.x = xo + round(sqrt(2) * penWidthOut * cos(M_PI_4 + theta));
1919  pt.y = yo + round(sqrt(2) * penWidthOut * sin(M_PI_4 + theta));
1920  PATH_AddEntry(pUpPath, &pt, (j == 0 ? PT_MOVETO : PT_LINETO));
1921  pt.x = xo + round(sqrt(2) * penWidthIn * cos(- M_PI_4 + theta));
1922  pt.y = yo + round(sqrt(2) * penWidthIn * sin(- M_PI_4 + theta));
1923  PATH_AddEntry(pUpPath, &pt, PT_LINETO);
1924  break;
1925  case PS_ENDCAP_FLAT :
1926  pt.x = xo + round(penWidthOut * cos(theta + M_PI_2));
1927  pt.y = yo + round(penWidthOut * sin(theta + M_PI_2));
1928  PATH_AddEntry(pUpPath, &pt, (j == 0 ? PT_MOVETO : PT_LINETO));
1929  pt.x = xo - round(penWidthIn * cos(theta + M_PI_2));
1930  pt.y = yo - round(penWidthIn * sin(theta + M_PI_2));
1931  PATH_AddEntry(pUpPath, &pt, PT_LINETO);
1932  break;
1933  case PS_ENDCAP_ROUND :
1934  default :
1935  corners[0].x = xo - penWidthIn;
1936  corners[0].y = yo - penWidthIn;
1937  corners[1].x = xo + penWidthOut;
1938  corners[1].y = yo + penWidthOut;
1939  PATH_DoArcPart(pUpPath , corners, theta + M_PI_2 , theta + 3 * M_PI_4, (j == 0 ? PT_MOVETO : FALSE));
1940  PATH_DoArcPart(pUpPath , corners, theta + 3 * M_PI_4 , theta + M_PI, FALSE);
1941  PATH_DoArcPart(pUpPath , corners, theta + M_PI, theta + 5 * M_PI_4, FALSE);
1942  PATH_DoArcPart(pUpPath , corners, theta + 5 * M_PI_4 , theta + 3 * M_PI_2, FALSE);
1943  break;
1944  }
1945  }
1946  /* Corpse of the path */
1947  else
1948  {
1949  /* Compute angle */
1950  INT previous, next;
1951  double xa, ya, xb, yb, xo, yo;
1952  double alpha, theta, miterWidth;
1953  DWORD _joint = joint;
1954  POINT pt;
1955  PPATH pInsidePath, pOutsidePath;
1956  if (j > 0 && j < pStrokes[i]->numEntriesUsed - 1)
1957  {
1958  previous = j - 1;
1959  next = j + 1;
1960  }
1961  else if (j == 0)
1962  {
1963  previous = pStrokes[i]->numEntriesUsed - 1;
1964  next = j + 1;
1965  }
1966  else
1967  {
1968  previous = j - 1;
1969  next = 0;
1970  }
1971  xo = pStrokes[i]->pPoints[j].x;
1972  yo = pStrokes[i]->pPoints[j].y;
1973  xa = pStrokes[i]->pPoints[previous].x;
1974  ya = pStrokes[i]->pPoints[previous].y;
1975  xb = pStrokes[i]->pPoints[next].x;
1976  yb = pStrokes[i]->pPoints[next].y;
1977  theta = atan2(yo - ya, xo - xa);
1978  alpha = atan2(yb - yo, xb - xo) - theta;
1979  if (alpha > 0) alpha -= M_PI;
1980  else alpha += M_PI;
1981  if (_joint == PS_JOIN_MITER && dc->dclevel.laPath.eMiterLimit < fabs(1 / sin(alpha / 2)))
1982  {
1983  _joint = PS_JOIN_BEVEL;
1984  }
1985  if (alpha > 0)
1986  {
1987  pInsidePath = pUpPath;
1988  pOutsidePath = pDownPath;
1989  }
1990  else if (alpha < 0)
1991  {
1992  pInsidePath = pDownPath;
1993  pOutsidePath = pUpPath;
1994  }
1995  else
1996  {
1997  continue;
1998  }
1999  /* Inside angle points */
2000  if (alpha > 0)
2001  {
2002  pt.x = xo - round(penWidthIn * cos(theta + M_PI_2));
2003  pt.y = yo - round(penWidthIn * sin(theta + M_PI_2));
2004  }
2005  else
2006  {
2007  pt.x = xo + round(penWidthIn * cos(theta + M_PI_2));
2008  pt.y = yo + round(penWidthIn * sin(theta + M_PI_2));
2009  }
2010  PATH_AddEntry(pInsidePath, &pt, PT_LINETO);
2011  if (alpha > 0)
2012  {
2013  pt.x = xo + round(penWidthIn * cos(M_PI_2 + alpha + theta));
2014  pt.y = yo + round(penWidthIn * sin(M_PI_2 + alpha + theta));
2015  }
2016  else
2017  {
2018  pt.x = xo - round(penWidthIn * cos(M_PI_2 + alpha + theta));
2019  pt.y = yo - round(penWidthIn * sin(M_PI_2 + alpha + theta));
2020  }
2021  PATH_AddEntry(pInsidePath, &pt, PT_LINETO);
2022  /* Outside angle point */
2023  switch(_joint)
2024  {
2025  case PS_JOIN_MITER :
2026  miterWidth = fabs(penWidthOut / cos(M_PI_2 - fabs(alpha) / 2));
2027  pt.x = xo + round(miterWidth * cos(theta + alpha / 2));
2028  pt.y = yo + round(miterWidth * sin(theta + alpha / 2));
2029  PATH_AddEntry(pOutsidePath, &pt, PT_LINETO);
2030  break;
2031  case PS_JOIN_BEVEL :
2032  if (alpha > 0)
2033  {
2034  pt.x = xo + round(penWidthOut * cos(theta + M_PI_2));
2035  pt.y = yo + round(penWidthOut * sin(theta + M_PI_2));
2036  }
2037  else
2038  {
2039  pt.x = xo - round(penWidthOut * cos(theta + M_PI_2));
2040  pt.y = yo - round(penWidthOut * sin(theta + M_PI_2));
2041  }
2042  PATH_AddEntry(pOutsidePath, &pt, PT_LINETO);
2043  if (alpha > 0)
2044  {
2045  pt.x = xo - round(penWidthOut * cos(M_PI_2 + alpha + theta));
2046  pt.y = yo - round(penWidthOut * sin(M_PI_2 + alpha + theta));
2047  }
2048  else
2049  {
2050  pt.x = xo + round(penWidthOut * cos(M_PI_2 + alpha + theta));
2051  pt.y = yo + round(penWidthOut * sin(M_PI_2 + alpha + theta));
2052  }
2053  PATH_AddEntry(pOutsidePath, &pt, PT_LINETO);
2054  break;
2055  case PS_JOIN_ROUND :
2056  default :
2057  if (alpha > 0)
2058  {
2059  pt.x = xo + round(penWidthOut * cos(theta + M_PI_2));
2060  pt.y = yo + round(penWidthOut * sin(theta + M_PI_2));
2061  }
2062  else
2063  {
2064  pt.x = xo - round(penWidthOut * cos(theta + M_PI_2));
2065  pt.y = yo - round(penWidthOut * sin(theta + M_PI_2));
2066  }
2067  PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO);
2068  pt.x = xo + round(penWidthOut * cos(theta + alpha / 2));
2069  pt.y = yo + round(penWidthOut * sin(theta + alpha / 2));
2070  PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO);
2071  if (alpha > 0)
2072  {
2073  pt.x = xo - round(penWidthOut * cos(M_PI_2 + alpha + theta));
2074  pt.y = yo - round(penWidthOut * sin(M_PI_2 + alpha + theta));
2075  }
2076  else
2077  {
2078  pt.x = xo + round(penWidthOut * cos(M_PI_2 + alpha + theta));
2079  pt.y = yo + round(penWidthOut * sin(M_PI_2 + alpha + theta));
2080  }
2081  PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO);
2082  break;
2083  }
2084  }
2085  }
2086  type = add_points( pNewPath, pUpPath->pPoints, pUpPath->numEntriesUsed, PT_LINETO );
2087  type[0] = PT_MOVETO;
2088  reverse_points( pDownPath->pPoints, pDownPath->numEntriesUsed );
2089  type = add_points( pNewPath, pDownPath->pPoints, pDownPath->numEntriesUsed, PT_LINETO );
2090  if (pStrokes[i]->pFlags[pStrokes[i]->numEntriesUsed - 1] & PT_CLOSEFIGURE) type[0] = PT_MOVETO;
2091 
2092  PATH_DestroyGdiPath(pStrokes[i]);
2093  ExFreePoolWithTag(pStrokes[i], TAG_PATH);
2094  PATH_DestroyGdiPath(pUpPath);
2095  ExFreePoolWithTag(pUpPath, TAG_PATH);
2096  PATH_DestroyGdiPath(pDownPath);
2097  ExFreePoolWithTag(pDownPath, TAG_PATH);
2098  }
2099  if (pStrokes) ExFreePoolWithTag(pStrokes, TAG_PATH);
2100 
2101  PATH_UnlockPath(flat_path);
2102  PATH_Delete(flat_path->BaseObject.hHmgr);
2103  pNewPath->state = PATH_Closed;
2104  PATH_UnlockPath(pNewPath);
2105  return pNewPath;
2106 }
2107 
2108 static inline INT int_from_fixed(FIXED f)
2109 {
2110  return (f.fract >= 0x8000) ? (f.value + 1) : f.value;
2111 }
2112 
2113 /**********************************************************************
2114  * PATH_BezierTo
2115  *
2116  * Internally used by PATH_add_outline
2117  */
2118 static
2119 VOID
2120 FASTCALL
2122  PPATH pPath,
2123  POINT *lppt,
2124  INT n)
2125 {
2126  if (n < 2) return;
2127 
2128  if (n == 2)
2129  {
2130  PATH_AddEntry(pPath, &lppt[1], PT_LINETO);
2131  }
2132  else if (n == 3)
2133  {
2134  add_points( pPath, lppt, 3, PT_BEZIERTO );
2135  }
2136  else
2137  {
2138  POINT pt[3];
2139  INT i = 0;
2140 
2141  pt[2] = lppt[0];
2142  n--;
2143 
2144  while (n > 2)
2145  {
2146  pt[0] = pt[2];
2147  pt[1] = lppt[i + 1];
2148  pt[2].x = (lppt[i + 2].x + lppt[i + 1].x) / 2;
2149  pt[2].y = (lppt[i + 2].y + lppt[i + 1].y) / 2;
2150  add_points( pPath, pt, 3, PT_BEZIERTO );
2151  n--;
2152  i++;
2153  }
2154 
2155  pt[0] = pt[2];
2156  pt[1] = lppt[i + 1];
2157  pt[2] = lppt[i + 2];
2158  add_points( pPath, pt, 3, PT_BEZIERTO );
2159  }
2160 }
2161 
2162 static
2163 BOOL
2164 FASTCALL
2166  PDC dc,
2167  PPATH pPath,
2168  INT x,
2169  INT y,
2171  DWORD size)
2172 {
2174  POINT pt;
2175  BOOL bResult = FALSE;
2176 
2177  start = header;
2178 
2179  while ((char *)header < (char *)start + size)
2180  {
2181  TTPOLYCURVE *curve;
2182 
2183  if (header->dwType != TT_POLYGON_TYPE)
2184  {
2185  DPRINT1("Unknown header type %lu\n", header->dwType);
2186  goto cleanup;
2187  }
2188 
2189  pt.x = x + int_from_fixed(header->pfxStart.x);
2190  pt.y = y - int_from_fixed(header->pfxStart.y);
2191  PATH_AddEntry(pPath, &pt, PT_MOVETO);
2192 
2193  curve = (TTPOLYCURVE *)(header + 1);
2194 
2195  while ((char *)curve < (char *)header + header->cb)
2196  {
2197  /*DPRINT1("curve->wType %d\n", curve->wType);*/
2198 
2199  switch(curve->wType)
2200  {
2201  case TT_PRIM_LINE:
2202  {
2203  WORD i;
2204 
2205  for (i = 0; i < curve->cpfx; i++)
2206  {
2207  pt.x = x + int_from_fixed(curve->apfx[i].x);
2208  pt.y = y - int_from_fixed(curve->apfx[i].y);
2209  PATH_AddEntry(pPath, &pt, PT_LINETO);
2210  }
2211  break;
2212  }
2213 
2214  case TT_PRIM_QSPLINE:
2215  case TT_PRIM_CSPLINE:
2216  {
2217  WORD i;
2218  POINTFX ptfx;
2219  POINT *pts = ExAllocatePoolWithTag(PagedPool, (curve->cpfx + 1) * sizeof(POINT), TAG_PATH);
2220 
2221  if (!pts) goto cleanup;
2222 
2223  ptfx = *(POINTFX *)((char *)curve - sizeof(POINTFX));
2224 
2225  pts[0].x = x + int_from_fixed(ptfx.x);
2226  pts[0].y = y - int_from_fixed(ptfx.y);
2227 
2228  for (i = 0; i < curve->cpfx; i++)
2229  {
2230  pts[i + 1].x = x + int_from_fixed(curve->apfx[i].x);
2231  pts[i + 1].y = y - int_from_fixed(curve->apfx[i].y);
2232  }
2233 
2234  PATH_BezierTo(pPath, pts, curve->cpfx + 1);
2235 
2237  break;
2238  }
2239 
2240  default:
2241  DPRINT1("Unknown curve type %04x\n", curve->wType);
2242  goto cleanup;
2243  }
2244 
2245  curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
2246  }
2247  header = (TTPOLYGONHEADER *)((char *)header + header->cb);
2248  }
2249 
2250  bResult = TRUE;
2251 
2252 cleanup:
2253  IntGdiCloseFigure(pPath);
2254  return bResult;
2255 }
2256 
2257 /**********************************************************************
2258  * PATH_ExtTextOut
2259  */
2260 BOOL
2261 FASTCALL
2263  PDC dc,
2264  INT x,
2265  INT y,
2266  UINT flags,
2267  const RECTL *lprc,
2268  LPCWSTR str,
2269  UINT count,
2270  const INT *dx)
2271 {
2272  PPATH pPath;
2273  unsigned int idx, ggo_flags = GGO_NATIVE;
2274  POINT offset = {0, 0};
2275 
2276  pPath = PATH_LockPath(dc->dclevel.hPath);
2277  if (!pPath)
2278  {
2279  return FALSE;
2280  }
2281 
2282  if (pPath->state != PATH_Open)
2283  {
2284  DPRINT1("PATH_ExtTextOut not open\n");
2285  return FALSE;
2286  }
2287 
2288  if (!count) return TRUE;
2289  if (flags & ETO_GLYPH_INDEX) ggo_flags |= GGO_GLYPH_INDEX;
2290 
2291  for (idx = 0; idx < count; idx++)
2292  {
2293  MAT2 identity = { {0, 1}, {0, 0}, {0, 0}, {0, 1} };
2294  GLYPHMETRICS gm;
2295  DWORD dwSize;
2296  void *outline;
2297 
2298  dwSize = ftGdiGetGlyphOutline(dc,
2299  str[idx],
2300  ggo_flags,
2301  &gm,
2302  0,
2303  NULL,
2304  &identity,
2305  TRUE);
2306  if (dwSize == GDI_ERROR)
2307  {
2308  PATH_UnlockPath(pPath);
2309  return FALSE;
2310  }
2311 
2312  /* Add outline only if char is printable */
2313  if (dwSize)
2314  {
2315  outline = ExAllocatePoolWithTag(PagedPool, dwSize, TAG_PATH);
2316  if (!outline)
2317  {
2318  PATH_UnlockPath(pPath);
2319  return FALSE;
2320  }
2321 
2323  str[idx],
2324  ggo_flags,
2325  &gm,
2326  dwSize,
2327  outline,
2328  &identity,
2329  TRUE);
2330 
2331  PATH_add_outline(dc, pPath, x + offset.x, y + offset.y, outline, dwSize);
2332 
2333  ExFreePoolWithTag(outline, TAG_PATH);
2334  }
2335 
2336  if (dx)
2337  {
2338  if (flags & ETO_PDY)
2339  {
2340  offset.x += dx[idx * 2];
2341  offset.y += dx[idx * 2 + 1];
2342  }
2343  else
2344  offset.x += dx[idx];
2345  }
2346  else
2347  {
2348  offset.x += gm.gmCellIncX;
2349  offset.y += gm.gmCellIncY;
2350  }
2351  }
2352  PATH_UnlockPath(pPath);
2353  return TRUE;
2354 }
2355 
2356 
2357 /***********************************************************************
2358  * Exported functions
2359  */
2360 
2361 BOOL
2362 APIENTRY
2364 {
2365  PDC dc = DC_LockDc(hDC);
2366  if (!dc)
2367  {
2369  return FALSE;
2370  }
2371 
2372  if (!dc->dclevel.hPath)
2373  {
2374  DC_UnlockDc(dc);
2375  return TRUE;
2376  }
2377 
2378  if (!PATH_Delete(dc->dclevel.hPath))
2379  {
2380  DC_UnlockDc(dc);
2381  return FALSE;
2382  }
2383 
2384  dc->dclevel.hPath = 0;
2385  dc->dclevel.flPath &= ~DCPATH_ACTIVE;
2386 
2387  DC_UnlockDc(dc);
2388  return TRUE;
2389 }
2390 
2391 BOOL
2392 APIENTRY
2394 {
2395  PPATH pPath;
2396  PDC dc;
2397 
2398  dc = DC_LockDc(hDC);
2399  if (!dc)
2400  {
2402  return FALSE;
2403  }
2404 
2405  /* If path is already open, do nothing. Check if not Save DC state */
2406  if ((dc->dclevel.flPath & DCPATH_ACTIVE) && !(dc->dclevel.flPath & DCPATH_SAVE))
2407  {
2408  DC_UnlockDc(dc);
2409  return TRUE;
2410  }
2411 
2412  if (dc->dclevel.hPath)
2413  {
2414  DPRINT("BeginPath 1 0x%p\n", dc->dclevel.hPath);
2415  if (!(dc->dclevel.flPath & DCPATH_SAVE))
2416  {
2417  // Remove previous handle.
2418  if (!PATH_Delete(dc->dclevel.hPath))
2419  {
2420  DC_UnlockDc(dc);
2421  return FALSE;
2422  }
2423  }
2424  else
2425  {
2426  // Clear flags and Handle.
2427  dc->dclevel.flPath &= ~(DCPATH_SAVE | DCPATH_ACTIVE);
2428  dc->dclevel.hPath = NULL;
2429  }
2430  }
2432  dc->dclevel.flPath |= DCPATH_ACTIVE; // Set active ASAP!
2433  dc->dclevel.hPath = pPath->BaseObject.hHmgr;
2434  IntGetCurrentPositionEx(dc, &pPath->pos);
2435  IntLPtoDP( dc, &pPath->pos, 1 );
2436  DPRINT("BP : Current pos X %d Y %d\n",pPath->pos.x, pPath->pos.y);
2437  PATH_UnlockPath(pPath);
2438  DC_UnlockDc(dc);
2439 
2440  if (!pPath)
2441  {
2442  return FALSE;
2443  }
2444  return TRUE;
2445 }
2446 
2447 BOOL
2448 APIENTRY
2450 {
2451  BOOL Ret = FALSE; // Default to failure
2452  PDC pDc;
2453  PPATH pPath;
2454 
2455  DPRINT("Enter %s\n", __FUNCTION__);
2456 
2457  pDc = DC_LockDc(hDC);
2458  if (!pDc)
2459  {
2461  return FALSE;
2462  }
2463 
2464  pPath = PATH_LockPath(pDc->dclevel.hPath);
2465  if (!pPath)
2466  {
2467  DC_UnlockDc(pDc);
2468  return FALSE;
2469  }
2470 
2471  if (pPath->state == PATH_Open)
2472  {
2473  IntGdiCloseFigure(pPath);
2474  Ret = TRUE;
2475  }
2476  else
2477  {
2479  }
2480 
2481  PATH_UnlockPath(pPath);
2482  DC_UnlockDc(pDc);
2483  return Ret;
2484 }
2485 
2486 BOOL
2487 APIENTRY
2489 {
2490  BOOL ret = TRUE;
2491  PPATH pPath;
2492  PDC dc;
2493 
2494  dc = DC_LockDc(hDC);
2495  if (!dc)
2496  {
2498  return FALSE;
2499  }
2500 
2501  pPath = PATH_LockPath(dc->dclevel.hPath);
2502  if (!pPath)
2503  {
2504  DC_UnlockDc(dc);
2505  return FALSE;
2506  }
2507 
2508  /* Check that path is currently being constructed */
2509  if ((pPath->state != PATH_Open) || !(dc->dclevel.flPath & DCPATH_ACTIVE))
2510  {
2511  DPRINT("EndPath ERROR! 0x%p\n", dc->dclevel.hPath);
2513  ret = FALSE;
2514  }
2515  /* Set flag to indicate that path is finished */
2516  else
2517  {
2518  DPRINT("EndPath 0x%p\n", dc->dclevel.hPath);
2519  pPath->state = PATH_Closed;
2520  dc->dclevel.flPath &= ~DCPATH_ACTIVE;
2521  }
2522 
2523  PATH_UnlockPath(pPath);
2524  DC_UnlockDc(dc);
2525  return ret;
2526 }
2527 
2528 BOOL
2529 APIENTRY
2531 {
2532  BOOL ret = FALSE;
2533  PPATH pPath, pNewPath;
2534  PDC_ATTR pdcattr;
2535  PDC dc;
2536 
2537  dc = DC_LockDc(hDC);
2538  if (!dc)
2539  {
2541  return FALSE;
2542  }
2543 
2544  pPath = PATH_LockPath(dc->dclevel.hPath);
2545  if (!pPath)
2546  {
2547  DC_UnlockDc(dc);
2548  return FALSE;
2549  }
2550 
2552 
2553  pdcattr = dc->pdcattr;
2554 
2555  if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
2556  DC_vUpdateLineBrush(dc);
2557 
2558  if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
2559  DC_vUpdateFillBrush(dc);
2560 
2561  pNewPath = PATH_FlattenPath(pPath);
2562 
2563  if (pNewPath->state != PATH_Closed)
2564  {
2566  }
2567  else if (pNewPath->numEntriesUsed)
2568  {
2569  ret = PATH_FillPath(dc, pNewPath);
2570  }
2571  else ret = TRUE;
2572 
2573  PATH_UnlockPath(pNewPath);
2574  PATH_Delete(pNewPath->BaseObject.hHmgr);
2575 
2576  PATH_UnlockPath(pPath);
2577  PATH_Delete(pPath->BaseObject.hHmgr);
2578  dc->dclevel.hPath = 0;
2579  dc->dclevel.flPath &= ~DCPATH_ACTIVE;
2580 
2581  DC_vFinishBlit(dc, NULL);
2582  DC_UnlockDc(dc);
2583  return ret;
2584 }
2585 
2586 BOOL
2587 APIENTRY
2589 {
2590  BOOL Ret = FALSE;
2591  DC *pDc;
2592  PPATH pPath, pNewPath = NULL;
2593 
2594  DPRINT("Enter %s\n", __FUNCTION__);
2595 
2596  pDc = DC_LockDc(hDC);
2597  if (!pDc)
2598  {
2600  return FALSE;
2601  }
2602 
2603  pPath = PATH_LockPath(pDc->dclevel.hPath);
2604  if (!pPath)
2605  {
2607  DC_UnlockDc(pDc);
2608  return FALSE;
2609  }
2610 
2611  if (pPath->state == PATH_Closed)
2612  {
2613  pNewPath = PATH_FlattenPath(pPath);
2614  }
2615 
2616  PATH_UnlockPath(pPath);
2617 
2618  if (pNewPath)
2619  {
2620  PATH_Delete(pDc->dclevel.hPath);
2621  pDc->dclevel.hPath = pNewPath->BaseObject.hHmgr;
2622  PATH_UnlockPath(pNewPath);
2623  Ret = TRUE;
2624  }
2625 
2626  DC_UnlockDc(pDc);
2627  return Ret;
2628 }
2629 
2630 _Success_(return != FALSE)
2631 BOOL
2632 APIENTRY
2633 NtGdiGetMiterLimit(
2634  _In_ HDC hdc,
2636 {
2637  DC *pDc;
2638  BOOL bResult = TRUE;
2639 
2640  if (!(pDc = DC_LockDc(hdc)))
2641  {
2643  return FALSE;
2644  }
2645 
2646  _SEH2_TRY
2647  {
2648  ProbeForWrite(pdwOut, sizeof(DWORD), 1);
2649  *pdwOut = pDc->dclevel.laPath.eMiterLimit;
2650  }
2652  {
2654  bResult = FALSE;
2655  }
2656  _SEH2_END;
2657 
2658  DC_UnlockDc(pDc);
2659  return bResult;
2660 
2661 }
2662 
2663 INT
2664 APIENTRY
2666  HDC hDC,
2667  LPPOINT Points,
2668  LPBYTE Types,
2669  INT nSize)
2670 {
2671  INT ret = -1;
2672  PPATH pPath;
2673 
2674  DC *dc = DC_LockDc(hDC);
2675  DPRINT("NtGdiGetPath start\n");
2676  if (!dc)
2677  {
2678  DPRINT1("Can't lock dc!\n");
2680  return -1;
2681  }
2682 
2683  pPath = PATH_LockPath(dc->dclevel.hPath);
2684  if (!pPath)
2685  {
2686  DC_UnlockDc(dc);
2687  return -1;
2688  }
2689 
2690  if (pPath->state != PATH_Closed)
2691  {
2693  goto done;
2694  }
2695 
2696  if (nSize == 0)
2697  {
2698  ret = pPath->numEntriesUsed;
2699  }
2700  else if (nSize < pPath->numEntriesUsed)
2701  {
2703  goto done;
2704  }
2705  else
2706  {
2707  _SEH2_TRY
2708  {
2709  memcpy(Points, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
2710  memcpy(Types, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
2711 
2712  /* Convert the points to logical coordinates */
2713  if (!GdiPathDPtoLP(dc, Points, pPath->numEntriesUsed))
2714  {
2716  _SEH2_LEAVE;
2717  }
2718 
2719  ret = pPath->numEntriesUsed;
2720  }
2722  {
2724  }
2725  _SEH2_END
2726  }
2727 
2728 done:
2729  DPRINT("NtGdiGetPath exit %d\n",ret);
2730  PATH_UnlockPath(pPath);
2731  DC_UnlockDc(dc);
2732  return ret;
2733 }
2734 
2735 HRGN
2736 APIENTRY
2738 {
2739  PPATH pPath, pNewPath;
2740  HRGN hrgnRval = 0;
2741  int Ret;
2742  PREGION Rgn;
2743  DC *pDc;
2744  PDC_ATTR pdcattr;
2745 
2746  DPRINT("Enter %s\n", __FUNCTION__);
2747 
2748  pDc = DC_LockDc(hDC);
2749  if (!pDc)
2750  {
2751  DPRINT("Failed to lock DC %p\n", hDC);
2753  return NULL;
2754  }
2755 
2756  pdcattr = pDc->pdcattr;
2757 
2758  pPath = PATH_LockPath(pDc->dclevel.hPath);
2759  if (!pPath)
2760  {
2761  DPRINT("Failed to lock DC path %p\n", pDc->dclevel.hPath);
2762  DC_UnlockDc(pDc);
2763  return NULL;
2764  }
2765 
2766  if (pPath->state != PATH_Closed)
2767  {
2768  // FIXME: Check that setlasterror is being called correctly
2769  DPRINT("Path is not closed!\n");
2771  }
2772  else
2773  {
2774  /* Create the region and fill it with the path strokes */
2776  if (!Rgn)
2777  {
2778  DPRINT("Failed to allocate a region\n");
2779  PATH_UnlockPath(pPath);
2780  DC_UnlockDc(pDc);
2781  return NULL;
2782  }
2783  hrgnRval = Rgn->BaseObject.hHmgr;
2784 
2785  pNewPath = PATH_FlattenPath(pPath);
2786 
2787  Ret = PATH_PathToRegion(pNewPath, pdcattr->jFillMode, Rgn);
2788 
2789  PATH_UnlockPath(pNewPath);
2790  PATH_Delete(pNewPath->BaseObject.hHmgr);
2791 
2792  if (!Ret)
2793  {
2794  DPRINT("PATH_PathToRegion failed\n");
2795  REGION_Delete(Rgn);
2796  hrgnRval = NULL;
2797  }
2798  else
2799  REGION_UnlockRgn(Rgn);
2800  }
2801 
2802  PATH_UnlockPath(pPath);
2803  PATH_Delete(pDc->dclevel.hPath);
2804  pDc->dclevel.hPath = NULL;
2805  pDc->dclevel.flPath &= ~DCPATH_ACTIVE;
2806 
2807  DC_UnlockDc(pDc);
2808  return hrgnRval;
2809 }
2810 
2811 BOOL
2812 APIENTRY
2814  IN HDC hdc,
2815  IN DWORD dwNew,
2817 {
2818  DC *pDc;
2819  gxf_long worker, worker1;
2820  BOOL bResult = TRUE;
2821 
2822  if (!(pDc = DC_LockDc(hdc)))
2823  {
2825  return FALSE;
2826  }
2827 
2828  worker.l = dwNew;
2829  worker1.f = pDc->dclevel.laPath.eMiterLimit;
2830  pDc->dclevel.laPath.eMiterLimit = worker.f;
2831 
2832  if (pdwOut)
2833  {
2834  _SEH2_TRY
2835  {
2836  ProbeForWrite(pdwOut, sizeof(DWORD), 1);
2837  *pdwOut = worker1.l;
2838  }
2840  {
2842  bResult = FALSE;
2843  }
2844  _SEH2_END;
2845  }
2846 
2847  DC_UnlockDc(pDc);
2848  return bResult;
2849 }
2850 
2851 BOOL
2852 APIENTRY
2854 {
2855  DC *pDc;
2856  PDC_ATTR pdcattr;
2857  PPATH pPath, pNewPath;
2858  BOOL bRet = FALSE;
2859 
2860  DPRINT("Enter %s\n", __FUNCTION__);
2861 
2862  if (!(pDc = DC_LockDc(hDC)))
2863  {
2865  return FALSE;
2866  }
2867  pPath = PATH_LockPath(pDc->dclevel.hPath);
2868  if (!pPath)
2869  {
2870  DC_UnlockDc(pDc);
2871  return FALSE;
2872  }
2873 
2875 
2876  pdcattr = pDc->pdcattr;
2877 
2878  if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
2879  DC_vUpdateFillBrush(pDc);
2880 
2881  if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
2882  DC_vUpdateLineBrush(pDc);
2883 
2884  pNewPath = PATH_FlattenPath(pPath);
2885 
2886  if (pNewPath->state != PATH_Closed)
2887  {
2889  }
2890  else if (pNewPath->numEntriesUsed)
2891  {
2892  bRet = PATH_FillPath(pDc, pNewPath);
2893  if (bRet) bRet = PATH_StrokePath(pDc, pNewPath);
2894  }
2895  else bRet = TRUE;
2896 
2897  PATH_UnlockPath(pNewPath);
2898  PATH_Delete(pNewPath->BaseObject.hHmgr);
2899 
2900  PATH_UnlockPath(pPath);
2901  PATH_Delete(pPath->BaseObject.hHmgr);
2902  pDc->dclevel.hPath = 0;
2903  pDc->dclevel.flPath &= ~DCPATH_ACTIVE;
2904 
2905  DC_vFinishBlit(pDc, NULL);
2906  DC_UnlockDc(pDc);
2907  return bRet;
2908 }
2909 
2910 BOOL
2911 APIENTRY
2913 {
2914  DC *pDc;
2915  PDC_ATTR pdcattr;
2916  PPATH pPath, pNewPath;
2917  BOOL bRet = FALSE;
2918 
2919  DPRINT("Enter %s\n", __FUNCTION__);
2920 
2921  if (!(pDc = DC_LockDc(hDC)))
2922  {
2924  return FALSE;
2925  }
2926 
2927  pPath = PATH_LockPath(pDc->dclevel.hPath);
2928  if (!pPath)
2929  {
2930  DC_UnlockDc(pDc);
2931  return FALSE;
2932  }
2933 
2935 
2936  pdcattr = pDc->pdcattr;
2937 
2938  if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
2939  DC_vUpdateLineBrush(pDc);
2940 
2941  pNewPath = PATH_FlattenPath(pPath);
2942 
2943  if (pNewPath->state != PATH_Closed)
2944  {
2946  }
2947  else bRet = PATH_StrokePath(pDc, pNewPath);
2948 
2949  PATH_UnlockPath(pNewPath);
2950  PATH_Delete(pNewPath->BaseObject.hHmgr);
2951 
2952  DC_vFinishBlit(pDc, NULL);
2953 
2954  PATH_UnlockPath(pPath);
2955  PATH_Delete(pPath->BaseObject.hHmgr);
2956  pDc->dclevel.hPath = 0;
2957  pDc->dclevel.flPath &= ~DCPATH_ACTIVE;
2958 
2959  DC_UnlockDc(pDc);
2960  return bRet;
2961 }
2962 
2963 BOOL
2964 APIENTRY
2966 {
2967  PPATH pPath;
2968  BOOL Ret = FALSE;
2969  PDC pdc = DC_LockDc(hDC);
2970  DPRINT("NtGdiWidenPat Enter\n");
2971  if (!pdc)
2972  {
2974  return FALSE;
2975  }
2976 
2977  pPath = PATH_WidenPath(pdc);
2978  if (pPath)
2979  {
2980  DPRINT("WindenPath New Path\n");
2981  PATH_Delete(pdc->dclevel.hPath);
2982  pdc->dclevel.hPath = pPath->BaseObject.hHmgr;
2983  Ret = TRUE;
2984  }
2985  DC_UnlockDc(pdc);
2986  DPRINT("NtGdiWidenPat Ret %d\n",Ret);
2987  return Ret;
2988 }
2989 
2990 /* EOF */
VOID FASTCALL PATH_NormalizePoint(FLOAT_POINT corners[], const FLOAT_POINT *pPoint, double *pX, double *pY)
Definition: path.c:383
_STLP_DECLSPEC complex< float > _STLP_CALL sqrt(const complex< float > &)
Definition: complex.cpp:188
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3706
BOOL APIENTRY NtGdiStrokeAndFillPath(HDC hDC)
Definition: path.c:2853
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define XForm2MatrixS(m, x)
Definition: coord.h:18
int numEntriesAllocated
Definition: path.h:47
_Check_return_ _CRTIMP double __cdecl ceil(_In_ double x)
FLOAT f
Definition: ntgdityp.h:414
BASEOBJECT BaseObject
Definition: region.h:11
#define HDC
Definition: msvc.h:22
#define IntDPtoLP(pdc, ppt, count)
Definition: coord.h:12
#define abs(i)
Definition: fconv.c:206
#define M_PI_4
Definition: port.h:153
#define IN
Definition: typedefs.h:38
BOOL NTAPI GreModifyWorldTransform(PDC pdc, const XFORML *pxform, DWORD dwMode)
Definition: coord.c:453
#define max(a, b)
Definition: svc.c:63
VOID FASTCALL PATH_EmptyPath(PPATH pPath)
Definition: path.c:246
int APIENTRY IntGdiSetMapMode(PDC dc, int MapMode)
Definition: coord.c:816
BOOL FASTCALL PATH_AddEntry(PPATH pPath, const POINT *pPoint, BYTE flags)
Definition: path.c:262
ULONG l
Definition: ntgdityp.h:415
POINTL ptlViewportOrg
Definition: ntgdihdl.h:340
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint 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 GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
unsigned short WORD
Definition: ntddk_ex.h:93
#define PS_ENDCAP_SQUARE
Definition: wingdi.h:593
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
valarray< _Tp > atan2(const valarray< _Tp > &__x, const valarray< _Tp > &__y)
Definition: _valarray.h:928
BOOL APIENTRY NtGdiBeginPath(HDC hDC)
Definition: path.c:2393
BOOL FASTCALL PATH_Rectangle(PDC dc, INT x1, INT y1, INT x2, INT y2)
Definition: path.c:613
_In_ int _Inout_ LPRECT lprc
Definition: winuser.h:4313
BOOL FASTCALL REGION_SetPolyPolygonRgn(_Inout_ PREGION prgn, _In_ const POINT *ppt, _In_ const ULONG *pcPoints, _In_ ULONG cPolygons, _In_ INT iMode)
Definition: region.c:3234
VOID FASTCALL DC_vUpdateLineBrush(PDC pdc)
Definition: dcobjs.c:62
FORCEINLINE PDC DC_LockDc(HDC hdc)
Definition: dc.h:219
long y
Definition: polytest.cpp:48
DWORD elpWidth
Definition: wingdi.h:1920
BOOL PATH_RestorePath(DC *dst, DC *src)
Definition: path.c:209
_In_ ULONG Mode
Definition: hubbusif.h:303
#define XFORMOBJ_bApplyXform
Definition: xformobj.h:11
static VOID FASTCALL PATH_BezierTo(PPATH pPath, POINT *lppt, INT n)
Definition: path.c:2121
#define FLOAT
Definition: i386-dis.c:516
long x
Definition: polytest.cpp:48
BOOL FASTCALL PATH_StrokePath(DC *dc, PPATH pPath)
Definition: path.c:1539
#define TT_POLYGON_TYPE
Definition: wingdi.h:1299
short value
Definition: wingdi.h:2447
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
BOOL FASTCALL IntGdiPaintRgn(_In_ PDC pdc, _In_ PREGION prgn)
Definition: bitblt.c:1227
#define pt(x, y)
Definition: drawing.c:79
HANDLE hpen
Definition: ntgdihdl.h:293
PPATH FASTCALL PATH_CreatePath(int count)
Definition: path.c:35
unsigned char * LPBYTE
Definition: typedefs.h:52
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
#define DC_PEN_DIRTY
Definition: ntgdihdl.h:158
BOOL FASTCALL PATH_MoveTo(PDC dc, PPATH pPath)
Definition: path.c:540
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
INT APIENTRY NtGdiGetPath(HDC hDC, LPPOINT Points, LPBYTE Types, INT nSize)
Definition: path.c:2665
*nSize LPSTR _Inout_ LPDWORD nSize
Definition: winbase.h:1973
#define HRGN
Definition: msvc.h:39
INT iMapMode
Definition: ntgdihdl.h:335
Definition: path.h:27
#define round(x)
Definition: path.c:1710
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define assert(x)
Definition: debug.h:53
BOOL FASTCALL PATH_PolyPolyline(PDC dc, const POINT *pts, const DWORD *counts, DWORD polylines)
Definition: path.c:1289
#define PS_JOIN_BEVEL
Definition: wingdi.h:595
static __inline INT GDI_ROUND(FLOAT val)
Definition: font.c:22
static void reverse_points(POINT *points, UINT count)
Definition: path.c:480
HDC dc
Definition: cylfrac.c:34
static __inline void INTERNAL_LPTODP_FLOAT(DC *dc, FLOAT_POINT *point)
Definition: gdifloat.h:27
#define PS_JOIN_MITER
Definition: wingdi.h:596
GLuint GLuint end
Definition: gl.h:1545
short gmCellIncY
Definition: wingdi.h:2423
#define MWT_MAX
Definition: wingdi.h:946
Definition: wingdi.h:2449
BOOL APIENTRY NtGdiStrokePath(HDC hDC)
Definition: path.c:2912
BOOL PATH_SavePath(DC *dst, DC *src)
Definition: path.c:187
HGDIOBJ hHmgr
Definition: gdiobj.h:40
FORCEINLINE VOID XFORMOBJ_vInit(OUT XFORMOBJ *pxo, IN MATRIX *pmx)
Definition: xformobj.h:21
#define FASTCALL
Definition: nt_native.h:50
int32_t INT
Definition: typedefs.h:56
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
POINTL point
Definition: edittest.c:50
DWORD DWORD
Definition: winlogon.h:75
DWORD ret
Definition: path.c:52
VOID FASTCALL PATH_ScaleNormalizedPoint(FLOAT_POINT corners[], double x, double y, POINT *pPoint)
Definition: path.c:363
#define GDI_OBJECT_TYPE_EXTPEN
Definition: gdi.h:55
BOOL FASTCALL PATH_PolyPolygon(PDC dc, const POINT *pts, const INT *counts, UINT polygons)
Definition: path.c:1239
#define PATH_LockPath(hPath)
Definition: path.h:61
LONG y
Definition: windef.h:343
BOOL FASTCALL PATH_Ellipse(PDC dc, INT x1, INT y1, INT x2, INT y2)
Definition: path.c:758
FIXED y
Definition: wingdi.h:2686
GLuint n
Definition: s_context.h:57
GLuint const GLubyte GLvoid * src
Definition: s_context.h:57
GLenum GLclampf GLint i
Definition: glfuncs.h:14
static void close_figure(PPATH path)
Definition: path.c:512
PREGION FASTCALL IntSysCreateRectpRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
Definition: region.c:2386
static PPATH FASTCALL PATH_WidenPath(DC *dc)
Definition: path.c:1715
#define FALSE
Definition: types.h:117
WORD fract
Definition: wingdi.h:2446
BOOL FASTCALL PATH_PolyBezierTo(PDC dc, const POINT *pts, DWORD cbPoints)
Definition: path.c:1082
#define ERROR_CAN_NOT_COMPLETE
Definition: winerror.h:582
#define a
Definition: ke_i.h:78
#define e
Definition: ke_i.h:82
Definition: path.h:18
#define _SEH2_END
Definition: pseh2_64.h:7
VOID FASTCALL IntGdiCloseFigure(PPATH pPath)
Definition: path.c:108
struct tagPOINTFX POINTFX
BOOL FASTCALL PATH_PathToRegion(PPATH pPath, INT Mode, PREGION Rgn)
Definition: path.c:1402
unsigned int idx
Definition: utils.c:36
DWORD elpPenStyle
Definition: wingdi.h:1919
PPATH FASTCALL PATH_FlattenPath(PPATH pPath)
Definition: path.c:1358
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define TAG_PATH
Definition: tags.h:25
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:79
HGDIOBJ hHmgr(VOID)
Definition: baseobj.hpp:95
HDC hdc
Definition: msvc.h:53
#define APIENTRY
Definition: nt_native.h:48
const WCHAR * str
#define TAG_BEZIER
Definition: tags.h:13
#define GGO_NATIVE
Definition: wingdi.h:848
_STLP_DECLSPEC complex< float > _STLP_CALL cos(const complex< float > &)
POINT * pPoints
Definition: path.h:44
BOOL FASTCALL PATH_RoundRect(DC *dc, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height)
Definition: path.c:663
BOOL FASTCALL PATH_PolyDraw(PDC dc, const POINT *pts, const BYTE *types, DWORD cbPoints)
Definition: path.c:1131
smooth NULL
Definition: ftsmooth.c:557
#define _Out_
Definition: no_sal2.h:323
LONG cx
Definition: windef.h:347
#define AD_CLOCKWISE
Definition: wingdi.h:666
void DPRINT(...)
Definition: polytest.cpp:61
static void update_current_pos(PPATH path)
Definition: path.c:505
BOOL APIENTRY NtGdiWidenPath(HDC hDC)
Definition: path.c:2965
#define PATH_UnlockPath(pPath)
Definition: path.h:62
Definition: region.h:7
BOOL FASTCALL IntGdiPolyline(DC *dc, LPPOINT pt, int Count)
Definition: line.c:293
int numEntriesUsed
Definition: path.h:46
#define ERROR_ARITHMETIC_OVERFLOW
Definition: winerror.h:351
#define PS_ENDCAP_ROUND
Definition: wingdi.h:592
static BYTE * add_points(PPATH path, const POINT *points, DWORD count, BYTE type)
Definition: path.c:466
#define TT_PRIM_CSPLINE
Definition: wingdi.h:1302
#define TT_PRIM_QSPLINE
Definition: wingdi.h:1301
#define PS_COSMETIC
Definition: wingdi.h:582
BYTE * pFlags
Definition: path.h:45
ULONG ulDirty_
Definition: ntgdihdl.h:291
#define GDI_HANDLE_GET_TYPE(h)
Definition: gdi.h:31
VOID FASTCALL IntGetCurrentPositionEx(PDC dc, LPPOINT pt)
Definition: line.c:130
#define XF_LTOL
Definition: winddi.h:3109
#define DIRTY_STYLESTATE
Definition: ntgdihdl.h:155
HDC hDC
Definition: wglext.h:521
GLfloat f
Definition: glext.h:7540
BOOL FASTCALL PATH_PolylineTo(PDC dc, const POINT *pts, DWORD cbPoints)
Definition: path.c:1215
POINT pos
Definition: path.h:49
Definition: polytest.cpp:40
static WCHAR no[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2375
unsigned int BOOL
Definition: ntddk_ex.h:94
VOID NTAPI GDIOBJ_vDeleteObject(POBJ pobj)
Definition: gdiobj.c:1106
#define GDI_OBJECT_TYPE_PEN
Definition: gdi.h:54
GLint GLint GLsizei width
Definition: gl.h:1546
VOID FASTCALL PATH_DestroyGdiPath(PPATH pPath)
Definition: path.c:80
Definition: cmds.c:130
POINTFX apfx[1]
Definition: wingdi.h:2691
BOOL APIENTRY NtGdiAbortPath(HDC hDC)
Definition: path.c:2363
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint 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 GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint GLenum GLfloat GLenum GLint GLenum GLsizei GLenum GLboolean GLenum GLdouble GLenum GLfloat GLenum GLenum GLfloat GLenum GLenum GLdouble GLenum GLenum GLint GLenum GLenum GLint GLenum GLuint GLenum GLvoid const GLubyte GLenum GLenum GLenum GLint GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLvoid GLenum GLint GLenum GLint GLenum GLenum GLint GLuint GLdouble GLfloat GLint GLshort GLubyte GLenum GLuint GLenum const GLfloat GLenum const GLint GLenum GLenum const GLfloat GLenum GLenum const GLint GLfloat const GLfloat GLenum 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 GLenum GLenum const GLfloat GLenum GLenum const GLint const GLdouble GLuint GLenum const GLbyte const GLdouble const GLfloat const GLint const GLshort GLdouble GLdouble GLdouble GLdouble GLdouble GLdouble GLenum GLint const GLfloat GLenum GLint const GLushort GLenum GLint GLenum GLint GLfloat GLfloat factor
Definition: glfuncs.h:212
BOOL FASTCALL PATH_DoArcPart(PPATH pPath, FLOAT_POINT corners[], double angleStart, double angleEnd, BYTE startEntryType)
Definition: path.c:840
#define PS_JOIN_ROUND
Definition: wingdi.h:597
static BOOL add_log_points_new_stroke(DC *dc, PPATH path, const POINT *points, DWORD count, BYTE type)
Definition: path.c:519
LONG x
Definition: windef.h:342
GLuint GLuint GLsizei count
Definition: gl.h:1545
BOOL APIENTRY NtGdiEndPath(HDC hDC)
Definition: path.c:2488
BOOL FASTCALL PATH_LineTo(PDC dc, INT x, INT y)
Definition: path.c:569
POINT * GDI_Bezier(const POINT *Points, INT count, INT *nPtsOut)
Definition: bezier.c:189
POINTFX pfxStart
Definition: wingdi.h:2696
GLbitfield flags
Definition: glext.h:7161
#define GM_COMPATIBLE
Definition: wingdi.h:862
BOOL PATH_CheckCorners(DC *dc, POINT corners[], INT x1, INT y1, INT x2, INT y2)
Definition: path.c:403
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLsizei const GLfloat * points
Definition: glext.h:8112
VOID NTAPI GDIOBJ_vUnlockObject(POBJ pobj)
Definition: gdiobj.c:875
BOOL FASTCALL PATH_PolyBezier(PDC dc, const POINT *pts, DWORD cbPoints)
Definition: path.c:1105
#define IntLPtoDP(pdc, ppt, count)
Definition: coord.h:7
#define GGO_GLYPH_INDEX
Definition: wingdi.h:853
#define DIRTY_FILL
Definition: ntgdihdl.h:145
_Success_(return!=FALSE)
Definition: path.c:2630
BYTE jFillMode
Definition: ntgdihdl.h:306
HRGN APIENTRY NtGdiPathToRegion(HDC hDC)
Definition: path.c:2737
#define MatrixS2XForm(x, m)
Definition: coord.h:19
SIZEL szlWindowExt
Definition: ntgdihdl.h:339
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define M_PI_2
Definition: port.h:185
static BOOL start_new_stroke(PPATH path)
Definition: path.c:492
BOOL APIENTRY NtGdiCloseFigure(HDC hDC)
Definition: path.c:2449
#define M_PI
Definition: compiler.h:348
static stack_node_t temp
Definition: rpn.c:18
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG _In_ LONG y2
Definition: winddi.h:3706
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
Definition: mesh.c:5325
#define GROW_FACTOR_DENOM
Definition: path.c:24
short gmCellIncX
Definition: wingdi.h:2422
#define _SEH2_LEAVE
Definition: pseh2_64.h:9
unsigned char BYTE
Definition: ntddk_ex.h:96
static INT int_from_fixed(FIXED f)
Definition: path.c:2108
_Check_return_ _CRT_JIT_INTRINSIC double __cdecl fabs(_In_ double x)
#define _In_
Definition: no_sal2.h:204
BOOL APIENTRY NtGdiFillPath(HDC hDC)
Definition: path.c:2530
BOOL APIENTRY NtGdiSetMiterLimit(IN HDC hdc, IN DWORD dwNew, IN OUT OPTIONAL PDWORD pdwOut)
Definition: path.c:2813
#define PS_TYPE_MASK
Definition: wingdi.h:601
static unsigned __int64 next
Definition: rand_nt.c:6
FORCEINLINE VOID DC_UnlockDc(PDC pdc)
Definition: dc.h:237
static BOOL FASTCALL PATH_add_outline(PDC dc, PPATH pPath, INT x, INT y, TTPOLYGONHEADER *header, DWORD size)
Definition: path.c:2165
BOOL FASTCALL PATH_AssignGdiPath(PPATH pPathDest, const PPATH pPathSrc)
Definition: path.c:166
Definition: path.h:19
char ACPI_OBJECT_TYPE * Types
Definition: acdebug.h:342
GLuint start
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
BOOL FASTCALL PATH_ExtTextOut(PDC dc, INT x, INT y, UINT flags, const RECTL *lprc, LPCWSTR str, UINT count, const INT *dx)
Definition: path.c:2262
Definition: services.c:311
#define _SEH2_TRY
Definition: pseh2_64.h:5
BOOL newStroke
Definition: path.h:48
ULONG FASTCALL ftGdiGetGlyphOutline(PDC dc, WCHAR wch, UINT iFormat, LPGLYPHMETRICS pgm, ULONG cjBuf, PVOID pvBuf, LPMAT2 pmat2, BOOL bIgnoreRotation)
Definition: freetype.c:3091
#define PS_ENDCAP_FLAT
Definition: wingdi.h:594
#define PS_ENDCAP_MASK
Definition: wingdi.h:600
BOOL FASTCALL PATH_Arc(PDC dc, INT x1, INT y1, INT x2, INT y2, INT xStart, INT yStart, INT xEnd, INT yEnd, INT direction, INT lines)
Definition: path.c:901
#define PS_JOIN_MASK
Definition: wingdi.h:598
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
FORCEINLINE PSIZEL DC_pszlViewportExt(PDC pdc)
Definition: coord.h:72
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
VOID FASTCALL PATH_InitGdiPath(PPATH pPath)
Definition: path.c:142
GLuint const GLubyte GLvoid const GLvoid * dst
Definition: s_context.h:57
#define DC_BRUSH_DIRTY
Definition: ntgdihdl.h:157
VOID FASTCALL DC_vPrepareDCsForBlit(PDC pdcDest, const RECT *rcDest, PDC pdcSrc, const RECT *rcSrc)
Definition: dclife.c:497
DWORD * PDWORD
Definition: pedump.c:68
BOOL APIENTRY NtGdiFlattenPath(HDC hDC)
Definition: path.c:2588
BOOL FASTCALL PATH_AddFlatBezier(PPATH pPath, POINT *pt, BOOL closed)
Definition: path.c:1329
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3706
#define ETO_PDY
Definition: wingdi.h:655
#define DPRINT1
Definition: precomp.h:8
VOID FASTCALL DC_vFinishBlit(PDC pdc1, PDC pdc2)
Definition: dclife.c:606
#define MWT_IDENTITY
Definition: wingdi.h:942
void * Realloc(void *, size_t)
#define CoordLPtoDP(pdc, ppt)
Definition: coord.h:10
#define NUM_ENTRIES_INITIAL
Definition: path.c:21
VOID FASTCALL REGION_UnlockRgn(_In_ PREGION prgn)
Definition: region.c:2352
#define PATH_AllocPathWithHandle()
Definition: path.h:60
#define MM_TEXT
Definition: wingdi.h:871
#define PT_CLOSEFIGURE
Definition: wingdi.h:885
#define OUT
Definition: typedefs.h:39
BOOL FASTCALL GdiPathDPtoLP(PDC pdc, PPOINT ppt, INT count)
Definition: path.c:125
#define GROW_FACTOR_NUMER
Definition: path.c:23
#define PT_LINETO
Definition: wingdi.h:883
GLclampf GLclampf GLclampf alpha
Definition: gl.h:1740
#define PT_MOVETO
Definition: wingdi.h:882
BOOL FASTCALL PATH_ReserveEntries(PPATH pPath, INT numEntries)
Definition: path.c:296
SIZEL szlViewportExt
Definition: ntgdihdl.h:341
unsigned int ULONG
Definition: retypes.h:1
BASEOBJECT BaseObject
Definition: path.h:29
BOOL FASTCALL IntGdiMoveToEx(DC *dc, int X, int Y, LPPOINT Point)
Definition: line.c:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define DIRTY_LINE
Definition: ntgdihdl.h:146
char * cleanup(char *str)
Definition: wpickclick.c:99
FLONG state
Definition: path.h:43
_Out_ PDWORD pdwOut
Definition: ntgdi.h:1813
#define __FUNCTION__
Definition: compiler.h:205
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
_STLP_DECLSPEC complex< float > _STLP_CALL sin(const complex< float > &)
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1097
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define PT_BEZIERTO
Definition: wingdi.h:884
_Check_return_ _CRTIMP double __cdecl floor(_In_ double x)
PREGION FASTCALL REGION_AllocUserRgnWithHandle(INT nRgn)
Definition: region.c:2273
#define GDI_ERROR
Definition: wingdi.h:1290
INT INT y
Definition: msvc.h:62
#define TT_PRIM_LINE
Definition: wingdi.h:1300
#define memset(x, y, z)
Definition: compat.h:39
VOID FASTCALL REGION_Delete(PREGION pRgn)
Definition: region.c:2428
LONG cy
Definition: windef.h:348
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
struct CFHEADER header
Definition: fdi.c:109
BOOL FASTCALL PATH_Delete(HPATH hPath)
Definition: path.c:90
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
POINTL ptlWindowOrg
Definition: ntgdihdl.h:338
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
BOOL FASTCALL PATH_FillPath(PDC dc, PPATH pPath)
Definition: path.c:1457
FIXED x
Definition: wingdi.h:2685
VOID FASTCALL DC_vUpdateFillBrush(PDC pdc)
Definition: dcobjs.c:16
static BYTE * add_log_points(DC *dc, PPATH path, const POINT *points, DWORD count, BYTE type)
Definition: path.c:449
GLintptr offset
Definition: glext.h:5920
INT x
Definition: msvc.h:62
INT NTAPI GreGetObject(IN HGDIOBJ hobj, IN INT cbCount, IN PVOID pvBuffer)
Definition: gdiobj.c:1259
#define GM_ADVANCED
Definition: wingdi.h:863
INT dx
Definition: msvc.h:65
INT iGraphicsMode
Definition: ntgdihdl.h:303
DWORD dwSize
Definition: wglext.h:734