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