ReactOS  0.4.11-dev-433-g473ca91
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  return PATH_FillPathEx(dc, pPath, NULL);
1462 }
1463 
1464 BOOL
1465 FASTCALL
1467  PDC dc,
1468  PPATH pPath,
1469  PBRUSH pbrFill)
1470 {
1471  INT mapMode, graphicsMode;
1472  SIZE ptViewportExt, ptWindowExt;
1473  POINTL ptViewportOrg, ptWindowOrg;
1474  XFORML xform;
1475  PREGION Rgn;
1476  PDC_ATTR pdcattr = dc->pdcattr;
1477 
1478  /* Allocate a temporary region */
1479  Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
1480  if (!Rgn)
1481  {
1483  return FALSE;
1484  }
1485 
1486  if (!PATH_PathToRegion(pPath, pdcattr->jFillMode, Rgn))
1487  {
1488  DPRINT("PFP : Fail P2R\n");
1489  /* EngSetLastError ? */
1490  REGION_Delete(Rgn);
1491  return FALSE;
1492  }
1493 
1494  /* Since PaintRgn interprets the region as being in logical coordinates
1495  * but the points we store for the path are already in device
1496  * coordinates, we have to set the mapping mode to MM_TEXT temporarily.
1497  * Using SaveDC to save information about the mapping mode / world
1498  * transform would be easier but would require more overhead, especially
1499  * now that SaveDC saves the current path.
1500  */
1501 
1502  /* Save the information about the old mapping mode */
1503  mapMode = pdcattr->iMapMode;
1504  ptViewportExt = pdcattr->szlViewportExt;
1505  ptViewportOrg = pdcattr->ptlViewportOrg;
1506  ptWindowExt = pdcattr->szlWindowExt;
1507  ptWindowOrg = pdcattr->ptlWindowOrg;
1508 
1509  /* Save world transform
1510  * NB: The Windows documentation on world transforms would lead one to
1511  * believe that this has to be done only in GM_ADVANCED; however, my
1512  * tests show that resetting the graphics mode to GM_COMPATIBLE does
1513  * not reset the world transform.
1514  */
1515  MatrixS2XForm(&xform, &dc->pdcattr->mxWorldToPage);
1516 
1517  /* Set MM_TEXT */
1519  pdcattr->ptlViewportOrg.x = 0;
1520  pdcattr->ptlViewportOrg.y = 0;
1521  pdcattr->ptlWindowOrg.x = 0;
1522  pdcattr->ptlWindowOrg.y = 0;
1523 
1524  graphicsMode = pdcattr->iGraphicsMode;
1525  pdcattr->iGraphicsMode = GM_ADVANCED;
1527  pdcattr->iGraphicsMode = graphicsMode;
1528 
1529  /* Paint the region */
1530  IntGdiFillRgn(dc, Rgn, pbrFill);
1531  REGION_Delete(Rgn);
1532  /* Restore the old mapping mode */
1533  IntGdiSetMapMode(dc, mapMode);
1534  pdcattr->szlViewportExt = ptViewportExt;
1535  pdcattr->ptlViewportOrg = ptViewportOrg;
1536  pdcattr->szlWindowExt = ptWindowExt;
1537  pdcattr->ptlWindowOrg = ptWindowOrg;
1538 
1539  /* Go to GM_ADVANCED temporarily to restore the world transform */
1540  graphicsMode = pdcattr->iGraphicsMode;
1541  pdcattr->iGraphicsMode = GM_ADVANCED;
1542  GreModifyWorldTransform(dc, &xform, MWT_SET);
1543  pdcattr->iGraphicsMode = graphicsMode;
1544  return TRUE;
1545 }
1546 
1547 BOOL
1548 FASTCALL
1550  DC *dc,
1551  PPATH pPath)
1552 {
1553  BOOL ret = FALSE;
1554  INT i = 0;
1555  INT nLinePts, nAlloc;
1556  POINT *pLinePts = NULL;
1557  POINT ptViewportOrg, ptWindowOrg;
1558  SIZE szViewportExt, szWindowExt;
1559  DWORD mapMode, graphicsMode;
1560  XFORM xform;
1561  PDC_ATTR pdcattr = dc->pdcattr;
1562 
1563  DPRINT("Enter %s\n", __FUNCTION__);
1564 
1565  /* Save the mapping mode info */
1566  mapMode = pdcattr->iMapMode;
1567 
1568  szViewportExt = *DC_pszlViewportExt(dc);
1569  ptViewportOrg = dc->pdcattr->ptlViewportOrg;
1570  szWindowExt = dc->pdcattr->szlWindowExt;
1571  ptWindowOrg = dc->pdcattr->ptlWindowOrg;
1572 
1573  MatrixS2XForm(&xform, &dc->pdcattr->mxWorldToPage);
1574 
1575  /* Set MM_TEXT */
1576  pdcattr->iMapMode = MM_TEXT;
1577  pdcattr->ptlViewportOrg.x = 0;
1578  pdcattr->ptlViewportOrg.y = 0;
1579  pdcattr->ptlWindowOrg.x = 0;
1580  pdcattr->ptlWindowOrg.y = 0;
1581  graphicsMode = pdcattr->iGraphicsMode;
1582  pdcattr->iGraphicsMode = GM_ADVANCED;
1584  pdcattr->iGraphicsMode = graphicsMode;
1585 
1586  /* Allocate enough memory for the worst case without beziers (one PT_MOVETO
1587  * and the rest PT_LINETO with PT_CLOSEFIGURE at the end) plus some buffer
1588  * space in case we get one to keep the number of reallocations small. */
1589  nAlloc = pPath->numEntriesUsed + 1 + 300;
1590  pLinePts = ExAllocatePoolWithTag(PagedPool, nAlloc * sizeof(POINT), TAG_PATH);
1591  if (!pLinePts)
1592  {
1593  DPRINT1("Can't allocate pool!\n");
1595  goto end;
1596  }
1597  nLinePts = 0;
1598 
1599  for (i = 0; i < pPath->numEntriesUsed; i++)
1600  {
1601  if ((i == 0 || (pPath->pFlags[i - 1] & PT_CLOSEFIGURE))
1602  && (pPath->pFlags[i] != PT_MOVETO))
1603  {
1604  DPRINT1("Expected PT_MOVETO %s, got path flag %d\n",
1605  i == 0 ? "as first point" : "after PT_CLOSEFIGURE",
1606  (INT)pPath->pFlags[i]);
1607  goto end;
1608  }
1609 
1610  switch(pPath->pFlags[i])
1611  {
1612  case PT_MOVETO:
1613  DPRINT("Got PT_MOVETO (%ld, %ld)\n",
1614  pPath->pPoints[i].x, pPath->pPoints[i].y);
1615  if (nLinePts >= 2) IntGdiPolyline(dc, pLinePts, nLinePts);
1616  nLinePts = 0;
1617  pLinePts[nLinePts++] = pPath->pPoints[i];
1618  break;
1619  case PT_LINETO:
1620  case (PT_LINETO | PT_CLOSEFIGURE):
1621  DPRINT("Got PT_LINETO (%ld, %ld)\n",
1622  pPath->pPoints[i].x, pPath->pPoints[i].y);
1623  pLinePts[nLinePts++] = pPath->pPoints[i];
1624  break;
1625  case PT_BEZIERTO:
1626  DPRINT("Got PT_BEZIERTO\n");
1627  if (pPath->pFlags[i + 1] != PT_BEZIERTO ||
1628  (pPath->pFlags[i + 2] & ~PT_CLOSEFIGURE) != PT_BEZIERTO)
1629  {
1630  DPRINT1("Path didn't contain 3 successive PT_BEZIERTOs\n");
1631  ret = FALSE;
1632  goto end;
1633  }
1634  else
1635  {
1636  INT nBzrPts, nMinAlloc;
1637  POINT *pBzrPts = GDI_Bezier(&pPath->pPoints[i - 1], 4, &nBzrPts);
1638  /* Make sure we have allocated enough memory for the lines of
1639  * this bezier and the rest of the path, assuming we won't get
1640  * another one (since we won't reallocate again then). */
1641  nMinAlloc = nLinePts + (pPath->numEntriesUsed - i) + nBzrPts;
1642  if (nAlloc < nMinAlloc)
1643  {
1644  // Reallocate memory
1645 
1646  POINT *Realloc = NULL;
1647  nAlloc = nMinAlloc * 2;
1648 
1649  Realloc = ExAllocatePoolWithTag(PagedPool,
1650  nAlloc * sizeof(POINT),
1651  TAG_PATH);
1652 
1653  if (!Realloc)
1654  {
1655  DPRINT1("Can't allocate pool!\n");
1656  ExFreePoolWithTag(pBzrPts, TAG_BEZIER);
1657  goto end;
1658  }
1659 
1660  memcpy(Realloc, pLinePts, nLinePts * sizeof(POINT));
1661  ExFreePoolWithTag(pLinePts, TAG_PATH);
1662  pLinePts = Realloc;
1663  }
1664  memcpy(&pLinePts[nLinePts], &pBzrPts[1], (nBzrPts - 1) * sizeof(POINT));
1665  nLinePts += nBzrPts - 1;
1666  ExFreePoolWithTag(pBzrPts, TAG_BEZIER);
1667  i += 2;
1668  }
1669  break;
1670  default:
1671  DPRINT1("Got path flag %d (not supported)\n", (INT)pPath->pFlags[i]);
1672  goto end;
1673  }
1674 
1675  if (pPath->pFlags[i] & PT_CLOSEFIGURE)
1676  {
1677  pLinePts[nLinePts++] = pLinePts[0];
1678  }
1679  }
1680  if (nLinePts >= 2)
1681  IntGdiPolyline(dc, pLinePts, nLinePts);
1682 
1683  ret = TRUE;
1684 
1685 end:
1686  if (pLinePts) ExFreePoolWithTag(pLinePts, TAG_PATH);
1687 
1688  /* Restore the old mapping mode */
1689  pdcattr->iMapMode = mapMode;
1690  pdcattr->szlWindowExt.cx = szWindowExt.cx;
1691  pdcattr->szlWindowExt.cy = szWindowExt.cy;
1692  pdcattr->ptlWindowOrg.x = ptWindowOrg.x;
1693  pdcattr->ptlWindowOrg.y = ptWindowOrg.y;
1694 
1695  pdcattr->szlViewportExt.cx = szViewportExt.cx;
1696  pdcattr->szlViewportExt.cy = szViewportExt.cy;
1697  pdcattr->ptlViewportOrg.x = ptViewportOrg.x;
1698  pdcattr->ptlViewportOrg.y = ptViewportOrg.y;
1699 
1700  /* Restore the world transform */
1701  XForm2MatrixS(&dc->pdcattr->mxWorldToPage, &xform);
1702 
1703  /* If we've moved the current point then get its new position
1704  which will be in device (MM_TEXT) co-ords, convert it to
1705  logical co-ords and re-set it. This basically updates
1706  dc->CurPosX|Y so that their values are in the correct mapping
1707  mode.
1708  */
1709  if (i > 0)
1710  {
1711  POINT pt;
1712  IntGetCurrentPositionEx(dc, &pt);
1713  IntDPtoLP(dc, &pt, 1);
1714  IntGdiMoveToEx(dc, pt.x, pt.y, NULL);
1715  }
1716  DPRINT("Leave %s, ret=%d\n", __FUNCTION__, ret);
1717  return ret;
1718 }
1719 
1720 #define round(x) ((int)((x)>0?(x)+0.5:(x)-0.5))
1721 
1722 static
1723 PPATH
1724 FASTCALL
1726 {
1727  INT i, j, numStrokes, numOldStrokes, penWidth, penWidthIn, penWidthOut, size, penStyle;
1728  PPATH pPath, flat_path, pNewPath, *pStrokes = NULL, *pOldStrokes, pUpPath, pDownPath;
1729  EXTLOGPEN *elp;
1730  BYTE *type;
1731  DWORD obj_type, joint, endcap, penType;
1732  PDC_ATTR pdcattr = dc->pdcattr;
1733 
1734  pPath = PATH_LockPath(dc->dclevel.hPath);
1735  if (!pPath)
1736  {
1738  return NULL;
1739  }
1740 
1741  if (pPath->state != PATH_Closed)
1742  {
1743  DPRINT("PWP 1\n");
1744  PATH_UnlockPath(pPath);
1746  return NULL;
1747  }
1748 
1749  size = GreGetObject(pdcattr->hpen, 0, NULL);
1750  if (!size)
1751  {
1752  DPRINT("PWP 2\n");
1753  PATH_UnlockPath(pPath);
1755  return FALSE;
1756  }
1757 
1759  if (elp == NULL)
1760  {
1761  DPRINT("PWP 3\n");
1762  PATH_UnlockPath(pPath);
1764  return FALSE;
1765  }
1766 
1767  GreGetObject(pdcattr->hpen, size, elp);
1768 
1769  obj_type = GDI_HANDLE_GET_TYPE(pdcattr->hpen);
1770  if (obj_type == GDI_OBJECT_TYPE_PEN)
1771  {
1772  penStyle = ((LOGPEN*)elp)->lopnStyle;
1773  }
1774  else if (obj_type == GDI_OBJECT_TYPE_EXTPEN)
1775  {
1776  penStyle = elp->elpPenStyle;
1777  }
1778  else
1779  {
1780  DPRINT("PWP 4\n");
1783  PATH_UnlockPath(pPath);
1784  return FALSE;
1785  }
1786 
1787  penWidth = elp->elpWidth;
1789 
1790  endcap = (PS_ENDCAP_MASK & penStyle);
1791  joint = (PS_JOIN_MASK & penStyle);
1792  penType = (PS_TYPE_MASK & penStyle);
1793 
1794  /* The function cannot apply to cosmetic pens */
1795  if (obj_type == GDI_OBJECT_TYPE_EXTPEN && penType == PS_COSMETIC)
1796  {
1797  DPRINT("PWP 5\n");
1798  PATH_UnlockPath(pPath);
1800  return FALSE;
1801  }
1802 
1803  if (!(flat_path = PATH_FlattenPath(pPath)))
1804  {
1805  PATH_UnlockPath(pPath);
1806  return NULL;
1807  }
1808  PATH_UnlockPath(pPath);
1809 
1810  penWidthIn = penWidth / 2;
1811  penWidthOut = penWidth / 2;
1812  if (penWidthIn + penWidthOut < penWidth)
1813  penWidthOut++;
1814 
1815  numStrokes = 0;
1816 
1817  for (i = 0, j = 0; i < flat_path->numEntriesUsed; i++, j++)
1818  {
1819  POINT point;
1820  if ((i == 0 || (flat_path->pFlags[i - 1] & PT_CLOSEFIGURE)) &&
1821  (flat_path->pFlags[i] != PT_MOVETO))
1822  {
1823  DPRINT1("Expected PT_MOVETO %s, got path flag %c\n",
1824  i == 0 ? "as first point" : "after PT_CLOSEFIGURE",
1825  flat_path->pFlags[i]);
1826  if (pStrokes)
1827  ExFreePoolWithTag(pStrokes, TAG_PATH);
1828  PATH_UnlockPath(flat_path);
1829  PATH_Delete(flat_path->BaseObject.hHmgr);
1830  return FALSE;
1831  }
1832  switch(flat_path->pFlags[i])
1833  {
1834  case PT_MOVETO:
1835  if (numStrokes > 0)
1836  {
1837  pStrokes[numStrokes - 1]->state = PATH_Closed;
1838  }
1839  numOldStrokes = numStrokes;
1840  numStrokes++;
1841  j = 0;
1842  if (numStrokes == 1)
1843  pStrokes = ExAllocatePoolWithTag(PagedPool, sizeof(*pStrokes), TAG_PATH);
1844  else
1845  {
1846  pOldStrokes = pStrokes; // Save old pointer.
1847  pStrokes = ExAllocatePoolWithTag(PagedPool, numStrokes * sizeof(*pStrokes), TAG_PATH);
1848  if (!pStrokes)
1849  {
1850  PATH_UnlockPath(flat_path);
1851  PATH_Delete(flat_path->BaseObject.hHmgr);
1852  return FALSE;
1853  }
1854  RtlCopyMemory(pStrokes, pOldStrokes, numOldStrokes * sizeof(PPATH));
1855  ExFreePoolWithTag(pOldStrokes, TAG_PATH); // Free old pointer.
1856  }
1857  if (!pStrokes)
1858  {
1859  PATH_UnlockPath(flat_path);
1860  PATH_Delete(flat_path->BaseObject.hHmgr);
1861  return FALSE;
1862  }
1863  pStrokes[numStrokes - 1] = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
1864  if (!pStrokes[numStrokes - 1])
1865  {
1866  ASSERT(FALSE); // FIXME
1867  }
1868  PATH_InitGdiPath(pStrokes[numStrokes - 1]);
1869  pStrokes[numStrokes - 1]->state = PATH_Open;
1870  case PT_LINETO:
1871  case (PT_LINETO | PT_CLOSEFIGURE):
1872  point.x = flat_path->pPoints[i].x;
1873  point.y = flat_path->pPoints[i].y;
1874  PATH_AddEntry(pStrokes[numStrokes - 1], &point, flat_path->pFlags[i]);
1875  break;
1876  case PT_BEZIERTO:
1877  /* Should never happen because of the FlattenPath call */
1878  DPRINT1("Should never happen\n");
1879  break;
1880  default:
1881  DPRINT1("Got path flag %c\n", flat_path->pFlags[i]);
1882  if (pStrokes)
1883  ExFreePoolWithTag(pStrokes, TAG_PATH);
1884  PATH_UnlockPath(flat_path);
1885  PATH_Delete(flat_path->BaseObject.hHmgr);
1886  return FALSE;
1887  }
1888  }
1889 
1890  pNewPath = PATH_CreatePath( flat_path->numEntriesUsed );
1891 
1892  for (i = 0; i < numStrokes; i++)
1893  {
1894  pUpPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
1895  PATH_InitGdiPath(pUpPath);
1896  pUpPath->state = PATH_Open;
1897  pDownPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
1898  PATH_InitGdiPath(pDownPath);
1899  pDownPath->state = PATH_Open;
1900 
1901  for (j = 0; j < pStrokes[i]->numEntriesUsed; j++)
1902  {
1903  /* Beginning or end of the path if not closed */
1904  if ((!(pStrokes[i]->pFlags[pStrokes[i]->numEntriesUsed - 1] & PT_CLOSEFIGURE)) && (j == 0 || j == pStrokes[i]->numEntriesUsed - 1))
1905  {
1906  /* Compute segment angle */
1907  double xo, yo, xa, ya, theta;
1908  POINT pt;
1909  FLOAT_POINT corners[2];
1910  if (j == 0)
1911  {
1912  xo = pStrokes[i]->pPoints[j].x;
1913  yo = pStrokes[i]->pPoints[j].y;
1914  xa = pStrokes[i]->pPoints[1].x;
1915  ya = pStrokes[i]->pPoints[1].y;
1916  }
1917  else
1918  {
1919  xa = pStrokes[i]->pPoints[j - 1].x;
1920  ya = pStrokes[i]->pPoints[j - 1].y;
1921  xo = pStrokes[i]->pPoints[j].x;
1922  yo = pStrokes[i]->pPoints[j].y;
1923  }
1924  theta = atan2(ya - yo, xa - xo);
1925  switch(endcap)
1926  {
1927  case PS_ENDCAP_SQUARE :
1928  pt.x = xo + round(sqrt(2) * penWidthOut * cos(M_PI_4 + theta));
1929  pt.y = yo + round(sqrt(2) * penWidthOut * sin(M_PI_4 + theta));
1930  PATH_AddEntry(pUpPath, &pt, (j == 0 ? PT_MOVETO : PT_LINETO));
1931  pt.x = xo + round(sqrt(2) * penWidthIn * cos(- M_PI_4 + theta));
1932  pt.y = yo + round(sqrt(2) * penWidthIn * sin(- M_PI_4 + theta));
1933  PATH_AddEntry(pUpPath, &pt, PT_LINETO);
1934  break;
1935  case PS_ENDCAP_FLAT :
1936  pt.x = xo + round(penWidthOut * cos(theta + M_PI_2));
1937  pt.y = yo + round(penWidthOut * sin(theta + M_PI_2));
1938  PATH_AddEntry(pUpPath, &pt, (j == 0 ? PT_MOVETO : PT_LINETO));
1939  pt.x = xo - round(penWidthIn * cos(theta + M_PI_2));
1940  pt.y = yo - round(penWidthIn * sin(theta + M_PI_2));
1941  PATH_AddEntry(pUpPath, &pt, PT_LINETO);
1942  break;
1943  case PS_ENDCAP_ROUND :
1944  default :
1945  corners[0].x = xo - penWidthIn;
1946  corners[0].y = yo - penWidthIn;
1947  corners[1].x = xo + penWidthOut;
1948  corners[1].y = yo + penWidthOut;
1949  PATH_DoArcPart(pUpPath , corners, theta + M_PI_2 , theta + 3 * M_PI_4, (j == 0 ? PT_MOVETO : FALSE));
1950  PATH_DoArcPart(pUpPath , corners, theta + 3 * M_PI_4 , theta + M_PI, FALSE);
1951  PATH_DoArcPart(pUpPath , corners, theta + M_PI, theta + 5 * M_PI_4, FALSE);
1952  PATH_DoArcPart(pUpPath , corners, theta + 5 * M_PI_4 , theta + 3 * M_PI_2, FALSE);
1953  break;
1954  }
1955  }
1956  /* Corpse of the path */
1957  else
1958  {
1959  /* Compute angle */
1960  INT previous, next;
1961  double xa, ya, xb, yb, xo, yo;
1962  double alpha, theta, miterWidth;
1963  DWORD _joint = joint;
1964  POINT pt;
1965  PPATH pInsidePath, pOutsidePath;
1966  if (j > 0 && j < pStrokes[i]->numEntriesUsed - 1)
1967  {
1968  previous = j - 1;
1969  next = j + 1;
1970  }
1971  else if (j == 0)
1972  {
1973  previous = pStrokes[i]->numEntriesUsed - 1;
1974  next = j + 1;
1975  }
1976  else
1977  {
1978  previous = j - 1;
1979  next = 0;
1980  }
1981  xo = pStrokes[i]->pPoints[j].x;
1982  yo = pStrokes[i]->pPoints[j].y;
1983  xa = pStrokes[i]->pPoints[previous].x;
1984  ya = pStrokes[i]->pPoints[previous].y;
1985  xb = pStrokes[i]->pPoints[next].x;
1986  yb = pStrokes[i]->pPoints[next].y;
1987  theta = atan2(yo - ya, xo - xa);
1988  alpha = atan2(yb - yo, xb - xo) - theta;
1989  if (alpha > 0) alpha -= M_PI;
1990  else alpha += M_PI;
1991  if (_joint == PS_JOIN_MITER && dc->dclevel.laPath.eMiterLimit < fabs(1 / sin(alpha / 2)))
1992  {
1993  _joint = PS_JOIN_BEVEL;
1994  }
1995  if (alpha > 0)
1996  {
1997  pInsidePath = pUpPath;
1998  pOutsidePath = pDownPath;
1999  }
2000  else if (alpha < 0)
2001  {
2002  pInsidePath = pDownPath;
2003  pOutsidePath = pUpPath;
2004  }
2005  else
2006  {
2007  continue;
2008  }
2009  /* Inside angle points */
2010  if (alpha > 0)
2011  {
2012  pt.x = xo - round(penWidthIn * cos(theta + M_PI_2));
2013  pt.y = yo - round(penWidthIn * sin(theta + M_PI_2));
2014  }
2015  else
2016  {
2017  pt.x = xo + round(penWidthIn * cos(theta + M_PI_2));
2018  pt.y = yo + round(penWidthIn * sin(theta + M_PI_2));
2019  }
2020  PATH_AddEntry(pInsidePath, &pt, PT_LINETO);
2021  if (alpha > 0)
2022  {
2023  pt.x = xo + round(penWidthIn * cos(M_PI_2 + alpha + theta));
2024  pt.y = yo + round(penWidthIn * sin(M_PI_2 + alpha + theta));
2025  }
2026  else
2027  {
2028  pt.x = xo - round(penWidthIn * cos(M_PI_2 + alpha + theta));
2029  pt.y = yo - round(penWidthIn * sin(M_PI_2 + alpha + theta));
2030  }
2031  PATH_AddEntry(pInsidePath, &pt, PT_LINETO);
2032  /* Outside angle point */
2033  switch(_joint)
2034  {
2035  case PS_JOIN_MITER :
2036  miterWidth = fabs(penWidthOut / cos(M_PI_2 - fabs(alpha) / 2));
2037  pt.x = xo + round(miterWidth * cos(theta + alpha / 2));
2038  pt.y = yo + round(miterWidth * sin(theta + alpha / 2));
2039  PATH_AddEntry(pOutsidePath, &pt, PT_LINETO);
2040  break;
2041  case PS_JOIN_BEVEL :
2042  if (alpha > 0)
2043  {
2044  pt.x = xo + round(penWidthOut * cos(theta + M_PI_2));
2045  pt.y = yo + round(penWidthOut * sin(theta + M_PI_2));
2046  }
2047  else
2048  {
2049  pt.x = xo - round(penWidthOut * cos(theta + M_PI_2));
2050  pt.y = yo - round(penWidthOut * sin(theta + M_PI_2));
2051  }
2052  PATH_AddEntry(pOutsidePath, &pt, PT_LINETO);
2053  if (alpha > 0)
2054  {
2055  pt.x = xo - round(penWidthOut * cos(M_PI_2 + alpha + theta));
2056  pt.y = yo - round(penWidthOut * sin(M_PI_2 + alpha + theta));
2057  }
2058  else
2059  {
2060  pt.x = xo + round(penWidthOut * cos(M_PI_2 + alpha + theta));
2061  pt.y = yo + round(penWidthOut * sin(M_PI_2 + alpha + theta));
2062  }
2063  PATH_AddEntry(pOutsidePath, &pt, PT_LINETO);
2064  break;
2065  case PS_JOIN_ROUND :
2066  default :
2067  if (alpha > 0)
2068  {
2069  pt.x = xo + round(penWidthOut * cos(theta + M_PI_2));
2070  pt.y = yo + round(penWidthOut * sin(theta + M_PI_2));
2071  }
2072  else
2073  {
2074  pt.x = xo - round(penWidthOut * cos(theta + M_PI_2));
2075  pt.y = yo - round(penWidthOut * sin(theta + M_PI_2));
2076  }
2077  PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO);
2078  pt.x = xo + round(penWidthOut * cos(theta + alpha / 2));
2079  pt.y = yo + round(penWidthOut * sin(theta + alpha / 2));
2080  PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO);
2081  if (alpha > 0)
2082  {
2083  pt.x = xo - round(penWidthOut * cos(M_PI_2 + alpha + theta));
2084  pt.y = yo - round(penWidthOut * sin(M_PI_2 + alpha + theta));
2085  }
2086  else
2087  {
2088  pt.x = xo + round(penWidthOut * cos(M_PI_2 + alpha + theta));
2089  pt.y = yo + round(penWidthOut * sin(M_PI_2 + alpha + theta));
2090  }
2091  PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO);
2092  break;
2093  }
2094  }
2095  }
2096  type = add_points( pNewPath, pUpPath->pPoints, pUpPath->numEntriesUsed, PT_LINETO );
2097  type[0] = PT_MOVETO;
2098  reverse_points( pDownPath->pPoints, pDownPath->numEntriesUsed );
2099  type = add_points( pNewPath, pDownPath->pPoints, pDownPath->numEntriesUsed, PT_LINETO );
2100  if (pStrokes[i]->pFlags[pStrokes[i]->numEntriesUsed - 1] & PT_CLOSEFIGURE) type[0] = PT_MOVETO;
2101 
2102  PATH_DestroyGdiPath(pStrokes[i]);
2103  ExFreePoolWithTag(pStrokes[i], TAG_PATH);
2104  PATH_DestroyGdiPath(pUpPath);
2105  ExFreePoolWithTag(pUpPath, TAG_PATH);
2106  PATH_DestroyGdiPath(pDownPath);
2107  ExFreePoolWithTag(pDownPath, TAG_PATH);
2108  }
2109  if (pStrokes) ExFreePoolWithTag(pStrokes, TAG_PATH);
2110 
2111  PATH_UnlockPath(flat_path);
2112  PATH_Delete(flat_path->BaseObject.hHmgr);
2113  pNewPath->state = PATH_Closed;
2114  PATH_UnlockPath(pNewPath);
2115  return pNewPath;
2116 }
2117 
2118 static inline INT int_from_fixed(FIXED f)
2119 {
2120  return (f.fract >= 0x8000) ? (f.value + 1) : f.value;
2121 }
2122 
2123 /**********************************************************************
2124  * PATH_BezierTo
2125  *
2126  * Internally used by PATH_add_outline
2127  */
2128 static
2129 VOID
2130 FASTCALL
2132  PPATH pPath,
2133  POINT *lppt,
2134  INT n)
2135 {
2136  if (n < 2) return;
2137 
2138  if (n == 2)
2139  {
2140  PATH_AddEntry(pPath, &lppt[1], PT_LINETO);
2141  }
2142  else if (n == 3)
2143  {
2144  add_points( pPath, lppt, 3, PT_BEZIERTO );
2145  }
2146  else
2147  {
2148  POINT pt[3];
2149  INT i = 0;
2150 
2151  pt[2] = lppt[0];
2152  n--;
2153 
2154  while (n > 2)
2155  {
2156  pt[0] = pt[2];
2157  pt[1] = lppt[i + 1];
2158  pt[2].x = (lppt[i + 2].x + lppt[i + 1].x) / 2;
2159  pt[2].y = (lppt[i + 2].y + lppt[i + 1].y) / 2;
2160  add_points( pPath, pt, 3, PT_BEZIERTO );
2161  n--;
2162  i++;
2163  }
2164 
2165  pt[0] = pt[2];
2166  pt[1] = lppt[i + 1];
2167  pt[2] = lppt[i + 2];
2168  add_points( pPath, pt, 3, PT_BEZIERTO );
2169  }
2170 }
2171 
2172 static
2173 BOOL
2174 FASTCALL
2176  PDC dc,
2177  PPATH pPath,
2178  INT x,
2179  INT y,
2181  DWORD size)
2182 {
2184  POINT pt;
2185  BOOL bResult = FALSE;
2186 
2187  start = header;
2188 
2189  while ((char *)header < (char *)start + size)
2190  {
2191  TTPOLYCURVE *curve;
2192 
2193  if (header->dwType != TT_POLYGON_TYPE)
2194  {
2195  DPRINT1("Unknown header type %lu\n", header->dwType);
2196  goto cleanup;
2197  }
2198 
2199  pt.x = x + int_from_fixed(header->pfxStart.x);
2200  pt.y = y - int_from_fixed(header->pfxStart.y);
2201  PATH_AddEntry(pPath, &pt, PT_MOVETO);
2202 
2203  curve = (TTPOLYCURVE *)(header + 1);
2204 
2205  while ((char *)curve < (char *)header + header->cb)
2206  {
2207  /*DPRINT1("curve->wType %d\n", curve->wType);*/
2208 
2209  switch(curve->wType)
2210  {
2211  case TT_PRIM_LINE:
2212  {
2213  WORD i;
2214 
2215  for (i = 0; i < curve->cpfx; i++)
2216  {
2217  pt.x = x + int_from_fixed(curve->apfx[i].x);
2218  pt.y = y - int_from_fixed(curve->apfx[i].y);
2219  PATH_AddEntry(pPath, &pt, PT_LINETO);
2220  }
2221  break;
2222  }
2223 
2224  case TT_PRIM_QSPLINE:
2225  case TT_PRIM_CSPLINE:
2226  {
2227  WORD i;
2228  POINTFX ptfx;
2229  POINT *pts = ExAllocatePoolWithTag(PagedPool, (curve->cpfx + 1) * sizeof(POINT), TAG_PATH);
2230 
2231  if (!pts) goto cleanup;
2232 
2233  ptfx = *(POINTFX *)((char *)curve - sizeof(POINTFX));
2234 
2235  pts[0].x = x + int_from_fixed(ptfx.x);
2236  pts[0].y = y - int_from_fixed(ptfx.y);
2237 
2238  for (i = 0; i < curve->cpfx; i++)
2239  {
2240  pts[i + 1].x = x + int_from_fixed(curve->apfx[i].x);
2241  pts[i + 1].y = y - int_from_fixed(curve->apfx[i].y);
2242  }
2243 
2244  PATH_BezierTo(pPath, pts, curve->cpfx + 1);
2245 
2247  break;
2248  }
2249 
2250  default:
2251  DPRINT1("Unknown curve type %04x\n", curve->wType);
2252  goto cleanup;
2253  }
2254 
2255  curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
2256  }
2257  header = (TTPOLYGONHEADER *)((char *)header + header->cb);
2258  }
2259 
2260  bResult = TRUE;
2261 
2262 cleanup:
2263  IntGdiCloseFigure(pPath);
2264  return bResult;
2265 }
2266 
2267 /**********************************************************************
2268  * PATH_ExtTextOut
2269  */
2270 BOOL
2271 FASTCALL
2273  PDC dc,
2274  INT x,
2275  INT y,
2276  UINT flags,
2277  const RECTL *lprc,
2278  LPCWSTR str,
2279  UINT count,
2280  const INT *dx)
2281 {
2282  PPATH pPath;
2283  unsigned int idx, ggo_flags = GGO_NATIVE;
2284  POINT offset = {0, 0};
2285 
2286  pPath = PATH_LockPath(dc->dclevel.hPath);
2287  if (!pPath)
2288  {
2289  return FALSE;
2290  }
2291 
2292  if (pPath->state != PATH_Open)
2293  {
2294  DPRINT1("PATH_ExtTextOut not open\n");
2295  return FALSE;
2296  }
2297 
2298  if (!count) return TRUE;
2299  if (flags & ETO_GLYPH_INDEX) ggo_flags |= GGO_GLYPH_INDEX;
2300 
2301  for (idx = 0; idx < count; idx++)
2302  {
2303  MAT2 identity = { {0, 1}, {0, 0}, {0, 0}, {0, 1} };
2304  GLYPHMETRICS gm;
2305  DWORD dwSize;
2306  void *outline;
2307 
2308  dwSize = ftGdiGetGlyphOutline(dc,
2309  str[idx],
2310  ggo_flags,
2311  &gm,
2312  0,
2313  NULL,
2314  &identity,
2315  TRUE);
2316  if (dwSize == GDI_ERROR)
2317  {
2318  PATH_UnlockPath(pPath);
2319  return FALSE;
2320  }
2321 
2322  /* Add outline only if char is printable */
2323  if (dwSize)
2324  {
2325  outline = ExAllocatePoolWithTag(PagedPool, dwSize, TAG_PATH);
2326  if (!outline)
2327  {
2328  PATH_UnlockPath(pPath);
2329  return FALSE;
2330  }
2331 
2333  str[idx],
2334  ggo_flags,
2335  &gm,
2336  dwSize,
2337  outline,
2338  &identity,
2339  TRUE);
2340 
2341  PATH_add_outline(dc, pPath, x + offset.x, y + offset.y, outline, dwSize);
2342 
2343  ExFreePoolWithTag(outline, TAG_PATH);
2344  }
2345 
2346  if (dx)
2347  {
2348  if (flags & ETO_PDY)
2349  {
2350  offset.x += dx[idx * 2];
2351  offset.y += dx[idx * 2 + 1];
2352  }
2353  else
2354  offset.x += dx[idx];
2355  }
2356  else
2357  {
2358  offset.x += gm.gmCellIncX;
2359  offset.y += gm.gmCellIncY;
2360  }
2361  }
2362  PATH_UnlockPath(pPath);
2363  return TRUE;
2364 }
2365 
2366 
2367 /***********************************************************************
2368  * Exported functions
2369  */
2370 
2371 BOOL
2372 APIENTRY
2374 {
2375  PDC dc = DC_LockDc(hDC);
2376  if (!dc)
2377  {
2379  return FALSE;
2380  }
2381 
2382  if (!dc->dclevel.hPath)
2383  {
2384  DC_UnlockDc(dc);
2385  return TRUE;
2386  }
2387 
2388  if (!PATH_Delete(dc->dclevel.hPath))
2389  {
2390  DC_UnlockDc(dc);
2391  return FALSE;
2392  }
2393 
2394  dc->dclevel.hPath = 0;
2395  dc->dclevel.flPath &= ~DCPATH_ACTIVE;
2396 
2397  DC_UnlockDc(dc);
2398  return TRUE;
2399 }
2400 
2401 BOOL
2402 APIENTRY
2404 {
2405  PPATH pPath;
2406  PDC dc;
2407 
2408  dc = DC_LockDc(hDC);
2409  if (!dc)
2410  {
2412  return FALSE;
2413  }
2414 
2415  /* If path is already open, do nothing. Check if not Save DC state */
2416  if ((dc->dclevel.flPath & DCPATH_ACTIVE) && !(dc->dclevel.flPath & DCPATH_SAVE))
2417  {
2418  DC_UnlockDc(dc);
2419  return TRUE;
2420  }
2421 
2422  if (dc->dclevel.hPath)
2423  {
2424  DPRINT("BeginPath 1 0x%p\n", dc->dclevel.hPath);
2425  if (!(dc->dclevel.flPath & DCPATH_SAVE))
2426  {
2427  // Remove previous handle.
2428  if (!PATH_Delete(dc->dclevel.hPath))
2429  {
2430  DC_UnlockDc(dc);
2431  return FALSE;
2432  }
2433  }
2434  else
2435  {
2436  // Clear flags and Handle.
2437  dc->dclevel.flPath &= ~(DCPATH_SAVE | DCPATH_ACTIVE);
2438  dc->dclevel.hPath = NULL;
2439  }
2440  }
2442  dc->dclevel.flPath |= DCPATH_ACTIVE; // Set active ASAP!
2443  dc->dclevel.hPath = pPath->BaseObject.hHmgr;
2444  IntGetCurrentPositionEx(dc, &pPath->pos);
2445  IntLPtoDP( dc, &pPath->pos, 1 );
2446  DPRINT("BP : Current pos X %d Y %d\n",pPath->pos.x, pPath->pos.y);
2447  PATH_UnlockPath(pPath);
2448  DC_UnlockDc(dc);
2449 
2450  if (!pPath)
2451  {
2452  return FALSE;
2453  }
2454  return TRUE;
2455 }
2456 
2457 BOOL
2458 APIENTRY
2460 {
2461  BOOL Ret = FALSE; // Default to failure
2462  PDC pDc;
2463  PPATH pPath;
2464 
2465  DPRINT("Enter %s\n", __FUNCTION__);
2466 
2467  pDc = DC_LockDc(hDC);
2468  if (!pDc)
2469  {
2471  return FALSE;
2472  }
2473 
2474  pPath = PATH_LockPath(pDc->dclevel.hPath);
2475  if (!pPath)
2476  {
2477  DC_UnlockDc(pDc);
2478  return FALSE;
2479  }
2480 
2481  if (pPath->state == PATH_Open)
2482  {
2483  IntGdiCloseFigure(pPath);
2484  Ret = TRUE;
2485  }
2486  else
2487  {
2489  }
2490 
2491  PATH_UnlockPath(pPath);
2492  DC_UnlockDc(pDc);
2493  return Ret;
2494 }
2495 
2496 BOOL
2497 APIENTRY
2499 {
2500  BOOL ret = TRUE;
2501  PPATH pPath;
2502  PDC dc;
2503 
2504  dc = DC_LockDc(hDC);
2505  if (!dc)
2506  {
2508  return FALSE;
2509  }
2510 
2511  pPath = PATH_LockPath(dc->dclevel.hPath);
2512  if (!pPath)
2513  {
2514  DC_UnlockDc(dc);
2515  return FALSE;
2516  }
2517 
2518  /* Check that path is currently being constructed */
2519  if ((pPath->state != PATH_Open) || !(dc->dclevel.flPath & DCPATH_ACTIVE))
2520  {
2521  DPRINT("EndPath ERROR! 0x%p\n", dc->dclevel.hPath);
2523  ret = FALSE;
2524  }
2525  /* Set flag to indicate that path is finished */
2526  else
2527  {
2528  DPRINT("EndPath 0x%p\n", dc->dclevel.hPath);
2529  pPath->state = PATH_Closed;
2530  dc->dclevel.flPath &= ~DCPATH_ACTIVE;
2531  }
2532 
2533  PATH_UnlockPath(pPath);
2534  DC_UnlockDc(dc);
2535  return ret;
2536 }
2537 
2538 BOOL
2539 APIENTRY
2541 {
2542  BOOL ret = FALSE;
2543  PPATH pPath, pNewPath;
2544  PDC_ATTR pdcattr;
2545  PDC dc;
2546 
2547  dc = DC_LockDc(hDC);
2548  if (!dc)
2549  {
2551  return FALSE;
2552  }
2553 
2554  pPath = PATH_LockPath(dc->dclevel.hPath);
2555  if (!pPath)
2556  {
2557  DC_UnlockDc(dc);
2558  return FALSE;
2559  }
2560 
2562 
2563  pdcattr = dc->pdcattr;
2564 
2565  if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
2566  DC_vUpdateLineBrush(dc);
2567 
2568  if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
2569  DC_vUpdateFillBrush(dc);
2570 
2571  pNewPath = PATH_FlattenPath(pPath);
2572 
2573  if (pNewPath->state != PATH_Closed)
2574  {
2576  }
2577  else if (pNewPath->numEntriesUsed)
2578  {
2579  ret = PATH_FillPath(dc, pNewPath);
2580  }
2581  else ret = TRUE;
2582 
2583  PATH_UnlockPath(pNewPath);
2584  PATH_Delete(pNewPath->BaseObject.hHmgr);
2585 
2586  PATH_UnlockPath(pPath);
2587  PATH_Delete(pPath->BaseObject.hHmgr);
2588  dc->dclevel.hPath = 0;
2589  dc->dclevel.flPath &= ~DCPATH_ACTIVE;
2590 
2591  DC_vFinishBlit(dc, NULL);
2592  DC_UnlockDc(dc);
2593  return ret;
2594 }
2595 
2596 BOOL
2597 APIENTRY
2599 {
2600  BOOL Ret = FALSE;
2601  DC *pDc;
2602  PPATH pPath, pNewPath = NULL;
2603 
2604  DPRINT("Enter %s\n", __FUNCTION__);
2605 
2606  pDc = DC_LockDc(hDC);
2607  if (!pDc)
2608  {
2610  return FALSE;
2611  }
2612 
2613  pPath = PATH_LockPath(pDc->dclevel.hPath);
2614  if (!pPath)
2615  {
2617  DC_UnlockDc(pDc);
2618  return FALSE;
2619  }
2620 
2621  if (pPath->state == PATH_Closed)
2622  {
2623  pNewPath = PATH_FlattenPath(pPath);
2624  }
2625 
2626  PATH_UnlockPath(pPath);
2627 
2628  if (pNewPath)
2629  {
2630  PATH_Delete(pDc->dclevel.hPath);
2631  pDc->dclevel.hPath = pNewPath->BaseObject.hHmgr;
2632  PATH_UnlockPath(pNewPath);
2633  Ret = TRUE;
2634  }
2635 
2636  DC_UnlockDc(pDc);
2637  return Ret;
2638 }
2639 
2640 _Success_(return != FALSE)
2641 BOOL
2642 APIENTRY
2643 NtGdiGetMiterLimit(
2644  _In_ HDC hdc,
2646 {
2647  DC *pDc;
2648  BOOL bResult = TRUE;
2649 
2650  if (!(pDc = DC_LockDc(hdc)))
2651  {
2653  return FALSE;
2654  }
2655 
2656  _SEH2_TRY
2657  {
2658  ProbeForWrite(pdwOut, sizeof(DWORD), 1);
2659  *pdwOut = pDc->dclevel.laPath.eMiterLimit;
2660  }
2662  {
2664  bResult = FALSE;
2665  }
2666  _SEH2_END;
2667 
2668  DC_UnlockDc(pDc);
2669  return bResult;
2670 
2671 }
2672 
2673 INT
2674 APIENTRY
2676  HDC hDC,
2677  LPPOINT Points,
2678  LPBYTE Types,
2679  INT nSize)
2680 {
2681  INT ret = -1;
2682  PPATH pPath;
2683 
2684  DC *dc = DC_LockDc(hDC);
2685  DPRINT("NtGdiGetPath start\n");
2686  if (!dc)
2687  {
2688  DPRINT1("Can't lock dc!\n");
2690  return -1;
2691  }
2692 
2693  pPath = PATH_LockPath(dc->dclevel.hPath);
2694  if (!pPath)
2695  {
2696  DC_UnlockDc(dc);
2697  return -1;
2698  }
2699 
2700  if (pPath->state != PATH_Closed)
2701  {
2703  goto done;
2704  }
2705 
2706  if (nSize == 0)
2707  {
2708  ret = pPath->numEntriesUsed;
2709  }
2710  else if (nSize < pPath->numEntriesUsed)
2711  {
2713  goto done;
2714  }
2715  else
2716  {
2717  _SEH2_TRY
2718  {
2719  memcpy(Points, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
2720  memcpy(Types, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
2721 
2722  /* Convert the points to logical coordinates */
2723  if (!GdiPathDPtoLP(dc, Points, pPath->numEntriesUsed))
2724  {
2726  _SEH2_LEAVE;
2727  }
2728 
2729  ret = pPath->numEntriesUsed;
2730  }
2732  {
2734  }
2735  _SEH2_END
2736  }
2737 
2738 done:
2739  DPRINT("NtGdiGetPath exit %d\n",ret);
2740  PATH_UnlockPath(pPath);
2741  DC_UnlockDc(dc);
2742  return ret;
2743 }
2744 
2745 HRGN
2746 APIENTRY
2748 {
2749  PPATH pPath, pNewPath;
2750  HRGN hrgnRval = 0;
2751  int Ret;
2752  PREGION Rgn;
2753  DC *pDc;
2754  PDC_ATTR pdcattr;
2755 
2756  DPRINT("Enter %s\n", __FUNCTION__);
2757 
2758  pDc = DC_LockDc(hDC);
2759  if (!pDc)
2760  {
2761  DPRINT("Failed to lock DC %p\n", hDC);
2763  return NULL;
2764  }
2765 
2766  pdcattr = pDc->pdcattr;
2767 
2768  pPath = PATH_LockPath(pDc->dclevel.hPath);
2769  if (!pPath)
2770  {
2771  DPRINT("Failed to lock DC path %p\n", pDc->dclevel.hPath);
2772  DC_UnlockDc(pDc);
2773  return NULL;
2774  }
2775 
2776  if (pPath->state != PATH_Closed)
2777  {
2778  // FIXME: Check that setlasterror is being called correctly
2779  DPRINT("Path is not closed!\n");
2781  }
2782  else
2783  {
2784  /* Create the region and fill it with the path strokes */
2786  if (!Rgn)
2787  {
2788  DPRINT("Failed to allocate a region\n");
2789  PATH_UnlockPath(pPath);
2790  DC_UnlockDc(pDc);
2791  return NULL;
2792  }
2793  hrgnRval = Rgn->BaseObject.hHmgr;
2794 
2795  pNewPath = PATH_FlattenPath(pPath);
2796 
2797  Ret = PATH_PathToRegion(pNewPath, pdcattr->jFillMode, Rgn);
2798 
2799  PATH_UnlockPath(pNewPath);
2800  PATH_Delete(pNewPath->BaseObject.hHmgr);
2801 
2802  if (!Ret)
2803  {
2804  DPRINT("PATH_PathToRegion failed\n");
2805  REGION_Delete(Rgn);
2806  hrgnRval = NULL;
2807  }
2808  else
2809  REGION_UnlockRgn(Rgn);
2810  }
2811 
2812  PATH_UnlockPath(pPath);
2813  PATH_Delete(pDc->dclevel.hPath);
2814  pDc->dclevel.hPath = NULL;
2815  pDc->dclevel.flPath &= ~DCPATH_ACTIVE;
2816 
2817  DC_UnlockDc(pDc);
2818  return hrgnRval;
2819 }
2820 
2821 BOOL
2822 APIENTRY
2824  IN HDC hdc,
2825  IN DWORD dwNew,
2827 {
2828  DC *pDc;
2829  gxf_long worker, worker1;
2830  BOOL bResult = TRUE;
2831 
2832  if (!(pDc = DC_LockDc(hdc)))
2833  {
2835  return FALSE;
2836  }
2837 
2838  worker.l = dwNew;
2839  worker1.f = pDc->dclevel.laPath.eMiterLimit;
2840  pDc->dclevel.laPath.eMiterLimit = worker.f;
2841 
2842  if (pdwOut)
2843  {
2844  _SEH2_TRY
2845  {
2846  ProbeForWrite(pdwOut, sizeof(DWORD), 1);
2847  *pdwOut = worker1.l;
2848  }
2850  {
2852  bResult = FALSE;
2853  }
2854  _SEH2_END;
2855  }
2856 
2857  DC_UnlockDc(pDc);
2858  return bResult;
2859 }
2860 
2861 BOOL
2862 APIENTRY
2864 {
2865  DC *pDc;
2866  PDC_ATTR pdcattr;
2867  PPATH pPath, pNewPath;
2868  BOOL bRet = FALSE;
2869 
2870  DPRINT("Enter %s\n", __FUNCTION__);
2871 
2872  if (!(pDc = DC_LockDc(hDC)))
2873  {
2875  return FALSE;
2876  }
2877  pPath = PATH_LockPath(pDc->dclevel.hPath);
2878  if (!pPath)
2879  {
2880  DC_UnlockDc(pDc);
2881  return FALSE;
2882  }
2883 
2885 
2886  pdcattr = pDc->pdcattr;
2887 
2888  if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
2889  DC_vUpdateFillBrush(pDc);
2890 
2891  if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
2892  DC_vUpdateLineBrush(pDc);
2893 
2894  pNewPath = PATH_FlattenPath(pPath);
2895 
2896  if (pNewPath->state != PATH_Closed)
2897  {
2899  }
2900  else if (pNewPath->numEntriesUsed)
2901  {
2902  bRet = PATH_FillPath(pDc, pNewPath);
2903  if (bRet) bRet = PATH_StrokePath(pDc, pNewPath);
2904  }
2905  else bRet = TRUE;
2906 
2907  PATH_UnlockPath(pNewPath);
2908  PATH_Delete(pNewPath->BaseObject.hHmgr);
2909 
2910  PATH_UnlockPath(pPath);
2911  PATH_Delete(pPath->BaseObject.hHmgr);
2912  pDc->dclevel.hPath = 0;
2913  pDc->dclevel.flPath &= ~DCPATH_ACTIVE;
2914 
2915  DC_vFinishBlit(pDc, NULL);
2916  DC_UnlockDc(pDc);
2917  return bRet;
2918 }
2919 
2920 BOOL
2921 APIENTRY
2923 {
2924  DC *pDc;
2925  PDC_ATTR pdcattr;
2926  PPATH pPath, pNewPath;
2927  BOOL bRet = FALSE;
2928 
2929  DPRINT("Enter %s\n", __FUNCTION__);
2930 
2931  if (!(pDc = DC_LockDc(hDC)))
2932  {
2934  return FALSE;
2935  }
2936 
2937  pPath = PATH_LockPath(pDc->dclevel.hPath);
2938  if (!pPath)
2939  {
2940  DC_UnlockDc(pDc);
2941  return FALSE;
2942  }
2943 
2945 
2946  pdcattr = pDc->pdcattr;
2947 
2948  if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
2949  DC_vUpdateLineBrush(pDc);
2950 
2951  pNewPath = PATH_FlattenPath(pPath);
2952 
2953  if (pNewPath->state != PATH_Closed)
2954  {
2956  }
2957  else bRet = PATH_StrokePath(pDc, pNewPath);
2958 
2959  PATH_UnlockPath(pNewPath);
2960  PATH_Delete(pNewPath->BaseObject.hHmgr);
2961 
2962  DC_vFinishBlit(pDc, NULL);
2963 
2964  PATH_UnlockPath(pPath);
2965  PATH_Delete(pPath->BaseObject.hHmgr);
2966  pDc->dclevel.hPath = 0;
2967  pDc->dclevel.flPath &= ~DCPATH_ACTIVE;
2968 
2969  DC_UnlockDc(pDc);
2970  return bRet;
2971 }
2972 
2973 BOOL
2974 APIENTRY
2976 {
2977  PPATH pPath;
2978  BOOL Ret = FALSE;
2979  PDC pdc = DC_LockDc(hDC);
2980  DPRINT("NtGdiWidenPat Enter\n");
2981  if (!pdc)
2982  {
2984  return FALSE;
2985  }
2986 
2987  pPath = PATH_WidenPath(pdc);
2988  if (pPath)
2989  {
2990  DPRINT("WindenPath New Path\n");
2991  PATH_Delete(pdc->dclevel.hPath);
2992  pdc->dclevel.hPath = pPath->BaseObject.hHmgr;
2993  Ret = TRUE;
2994  }
2995  DC_UnlockDc(pdc);
2996  DPRINT("NtGdiWidenPat Ret %d\n",Ret);
2997  return Ret;
2998 }
2999 
3000 /* 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:2863
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define XForm2MatrixS(m, x)
Definition: coord.h:18
int numEntriesAllocated
Definition: path.h:56
_Check_return_ _CRTIMP double __cdecl ceil(_In_ double x)
FLOAT f
Definition: ntgdityp.h:420
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:421
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:2403
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:4334
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
#define MWT_SET
Definition: ntgdityp.h:177
_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:2131
#define FLOAT
Definition: i386-dis.c:516
long x
Definition: polytest.cpp:48
BOOL FASTCALL PATH_StrokePath(DC *dc, PPATH pPath)
Definition: path.c:1549
#define TT_POLYGON_TYPE
Definition: wingdi.h:1299
short value
Definition: wingdi.h:2447
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#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:2675
*nSize LPSTR _Inout_ LPDWORD nSize
Definition: winbase.h:2024
#define HRGN
Definition: msvc.h:39
INT iMapMode
Definition: ntgdihdl.h:335
Definition: path.h:34
GLintptr offset
Definition: glext.h:5920
#define round(x)
Definition: path.c:1720
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
Definition: wingdi.h:2449
BOOL APIENTRY NtGdiStrokePath(HDC hDC)
Definition: path.c:2922
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:84
DWORD ret
Definition: path.c:47
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:70
LONG y
Definition: windef.h:320
_SEH2_TRY
Definition: create.c:4250
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:1725
#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
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:41
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:80
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:53
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:416
#define _Out_
Definition: no_sal2.h:323
LONG cx
Definition: windef.h:324
#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:2975
#define PATH_UnlockPath(pPath)
Definition: path.h:71
Definition: region.h:7
BOOL FASTCALL IntGdiPolyline(DC *dc, LPPOINT pt, int Count)
Definition: line.c:293
int numEntriesUsed
Definition: path.h:55
#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:54
ULONG ulDirty_
Definition: ntgdihdl.h:291
Definition: types.h:100
#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:58
Definition: polytest.cpp:40
static WCHAR no[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2340
unsigned int BOOL
Definition: ntddk_ex.h:94
GLsizeiptr size
Definition: glext.h:5919
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:2373
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:319
GLuint GLuint GLsizei count
Definition: gl.h:1545
BOOL APIENTRY NtGdiEndPath(HDC hDC)
Definition: path.c:2498
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:2640
BYTE jFillMode
Definition: ntgdihdl.h:306
HRGN APIENTRY NtGdiPathToRegion(HDC hDC)
Definition: path.c:2747
#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:2459
#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:5329
#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:2118
_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:2540
BOOL APIENTRY NtGdiSetMiterLimit(IN HDC hdc, IN DWORD dwNew, IN OUT OPTIONAL PDWORD pdwOut)
Definition: path.c:2823
BOOL IntGdiFillRgn(_In_ PDC pdc, _In_ PREGION prgn, _In_opt_ PBRUSH pbrFill)
Definition: bitblt.c:1126
_SEH2_END
Definition: create.c:4424
#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:2175
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
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:2272
Definition: services.c:325
BOOL FASTCALL PATH_FillPathEx(PDC dc, PPATH pPath, PBRUSH pbrFill)
Definition: path.c:1466
BOOL newStroke
Definition: path.h:57
ULONG FASTCALL ftGdiGetGlyphOutline(PDC dc, WCHAR wch, UINT iFormat, LPGLYPHMETRICS pgm, ULONG cjBuf, PVOID pvBuf, LPMAT2 pmat2, BOOL bIgnoreRotation)
Definition: freetype.c:3426
#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:2598
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:69
#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:36
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:52
_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:1099
#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:325
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
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