ReactOS  r76032
drawing.c
Go to the documentation of this file.
1 /*
2 App Software Licence
3 --------------------
4 This package includes software which is copyright (c) L. Patrick.
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 
11 1. Redistributions of source code must retain the above copyright
12  notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14  notice, this list of conditions and the following disclaimer in the
15  documentation and/or other materials provided with the distribution.
16 3. You may not sell this software package.
17 4. You may include this software in a distribution of other software,
18  and you may charge a nominal fee for the media used.
19 5. You may sell derivative programs, providing that such programs
20  simply use this software in a compiled form.
21 6. You may sell derivative programs which use a compiled, modified
22  version of this software, provided that you have attempted as
23  best as you can to propagate all modifications made to the source
24  code files of this software package back to the original author(s)
25  of this package.
26 
27 THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS AS IS, AND
28 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
31 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 SUCH DAMAGE.
38 */
39 /* Copyright (c) L. Patrick
40 
41  This file is part of the App cross-platform programming package.
42  You may redistribute it and/or modify it under the terms of the
43  App Software License. See the file LICENSE.TXT for details.
44 
45  http://enchantia.com/software/graphapp/
46  http://www.it.usyd.edu.au/~graphapp/
47 */
48 /*
49  Modified for ReactOS
50  */
51 
52 #include <win32k.h>
53 
54 #define NDEBUG
55 #include <debug.h>
56 
57 
58 #define DEGREES_TO_RADIANS(deg) ((deg)*2*M_PI/360)
59 
60 typedef struct _Rect
61 {
62  int x, y; /* Top-left point inside rect */
63  int width, height; /* Width and height of rect */
64 } Rect, *PRect;
65 
66 int FASTCALL IntFillRect(DC *dc, INT XLeft, INT YLeft, INT Width, INT Height, PBRUSH pbrush, BOOL Pen);
67 //int FASTCALL app_fill_rect(DC *dc, Rect r, PBRUSH pbrush, BOOL Pen);
68 
69 static
70 POINT
71 NTAPI
72 app_new_point(int x, int y)
73 {
74  POINT p;
75  p.x = x;
76  p.y = y;
77  return p;
78 }
79 #define pt(x,y) app_new_point((x),(y))
80 
81 static
82 Rect
83 NTAPI
84 rect(int x, int y, int width, int height)
85 {
86  Rect r;
87  r.x = x;
88  r.y = y;
89  r.width = width;
90  r.height = height;
91  return r;
92 }
93 
94 
95 /*
96  * app_window_fill_rect:
97  *
98  * Fill a rectangle with colour, in a window.
99  *
100  * This function implements client-side clipping, so that
101  * we never rely on the GDI system to do clipping, except if
102  * the destination is a window which is partially obscured.
103  * In that situation we must rely on the GDI system because there
104  * is no way for the program to know which portions of the
105  * window are currently obscured.
106  */
107 #define app_fill_rect( dc, r, BrushObj, Pen) \
108  IntFillRect(dc, r.x, r.y, r.width, r.height, BrushObj, Pen)
109 
110 /*
111  * Drawing an ellipse with a certain line thickness.
112  * Use an inner and and outer ellipse and fill the spaces between.
113  * The inner ellipse uses all UPPERCASE letters, the outer lowercase.
114  *
115  * This algorithm is based on the fill_ellipse algorithm presented
116  * above, but uses two ellipse calculations, and some fix-up code
117  * to avoid pathological cases where the inner ellipse is almost
118  * the same size as the outer (in which case the border of the
119  * elliptical curve might otherwise have appeared broken).
120  */
121 static
122 int
123 NTAPI
125 {
126  /* Outer ellipse: e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
127 
128  int a = r.width / 2;
129  int b = r.height / 2;
130  int x = 0;
131  int y = b;
132  long a2 = a*a;
133  long b2 = b*b;
134  long xcrit = (3 * a2 / 4) + 1;
135  long ycrit = (3 * b2 / 4) + 1;
136  long t = b2 + a2 - 2*a2*b; /* t = e(x+1,y-1) */
137  long dxt = b2*(3+x+x);
138  long dyt = a2*(3-y-y);
139  int d2xt = b2+b2;
140  int d2yt = a2+a2;
141 
142  int w = pbrush->lWidth;
143 
144  /* Inner ellipse: E(X,Y) = B*B*X*X + A*A*Y*Y - A*A*B*B */
145 
146  int A = a-w > 0 ? a-w : 0;
147  int B = b-w > 0 ? b-w : 0;
148  int X = 0;
149  int Y = B;
150  long A2 = A*A;
151  long B2 = B*B;
152  long XCRIT = (3 * A2 / 4) + 1;
153  long YCRIT = (3 * B2 / 4) + 1;
154  long T = B2 + A2 - 2*A2*B; /* T = E(X+1,Y-1) */
155  long DXT = B2*(3+X+X);
156  long DYT = A2*(3-Y-Y);
157  int D2XT = B2+B2;
158  int D2YT = A2+A2;
159 
160  int movedown, moveout;
161  int innerX = 0, prevx, prevy, W;
162  Rect r1, r2;
163  int result = 1;
164 
165  if ((r.width <= 2) || (r.height <= 2))
166  return app_fill_rect(g, r, pbrush, TRUE);
167 
168  r1.x = r.x + a;
169  r1.y = r.y;
170  r1.width = r.width & 1; /* i.e. if width is odd */
171  r1.height = 1;
172 
173  r2 = r1;
174  r2.y = r.y + r.height - 1;
175 
176  prevx = r1.x;
177  prevy = r1.y;
178 
179  while (y > 0)
180  {
181  while (Y == y)
182  {
183  innerX = X;
184 
185  if (T + A2*Y < XCRIT) /* E(X+1,Y-1/2) <= 0 */
186  {
187  /* Move outwards to encounter edge */
188  X += 1;
189  T += DXT;
190  DXT += D2XT;
191  }
192  else if (T - B2*X >= YCRIT) /* e(x+1/2,y-1) > 0 */
193  {
194  /* Drop down one line */
195  Y -= 1;
196  T += DYT;
197  DYT += D2YT;
198  }
199  else
200  {
201  /* Drop diagonally down and out */
202  X += 1;
203  Y -= 1;
204  T += DXT + DYT;
205  DXT += D2XT;
206  DYT += D2YT;
207  }
208  }
209 
210  movedown = moveout = 0;
211 
212  W = x - innerX;
213  if (r1.x + W < prevx)
214  W = prevx - r1.x;
215  if (W < w)
216  W = w;
217 
218  if (t + a2*y < xcrit) /* e(x+1,y-1/2) <= 0 */
219  {
220  /* Move outwards to encounter edge */
221  x += 1;
222  t += dxt;
223  dxt += d2xt;
224 
225  moveout = 1;
226  }
227  else if (t - b2*x >= ycrit) /* e(x+1/2,y-1) > 0 */
228  {
229  /* Drop down one line */
230  y -= 1;
231  t += dyt;
232  dyt += d2yt;
233 
234  movedown = 1;
235  }
236  else
237  {
238  /* Drop diagonally down and out */
239  x += 1;
240  y -= 1;
241  t += dxt + dyt;
242  dxt += d2xt;
243  dyt += d2yt;
244 
245  movedown = 1;
246  moveout = 1;
247  }
248 
249  if (movedown)
250  {
251  if (r1.width == 0)
252  {
253  r1.x -= 1;
254  r1.width += 2;
255  r2.x -= 1;
256  r2.width += 2;
257  moveout = 0;
258  }
259 
260  if (r1.x < r.x)
261  r1.x = r2.x = r.x;
262  if (r1.width > r.width)
263  r1.width = r2.width = r.width;
264  if (r1.y == r2.y-1)
265  {
266  r1.x = r2.x = r.x;
267  r1.width = r2.width = r.width;
268  }
269 
270  if ((r1.y < r.y+w) || (r1.x+W >= r1.x+r1.width-W))
271  {
272  result &= app_fill_rect(g, r1, pbrush, TRUE);
273  result &= app_fill_rect(g, r2, pbrush, TRUE);
274 
275  prevx = r1.x;
276  prevy = r1.y;
277  }
278  else if (r1.y+r1.height < r2.y)
279  {
280  /* Draw distinct rectangles */
281  result &= app_fill_rect(g, rect(r1.x,r1.y,
282  W,1), pbrush, TRUE);
283  result &= app_fill_rect(g, rect(
284  r1.x+r1.width-W,r1.y,W,1), pbrush, TRUE);
285  result &= app_fill_rect(g, rect(r2.x,
286  r2.y,W,1), pbrush, TRUE);
287  result &= app_fill_rect(g, rect(
288  r2.x+r2.width-W,r2.y,W,1), pbrush, TRUE);
289 
290  prevx = r1.x;
291  prevy = r1.y;
292  }
293 
294  /* Move down */
295  r1.y += 1;
296  r2.y -= 1;
297  }
298 
299  if (moveout)
300  {
301  /* Move outwards */
302  r1.x -= 1;
303  r1.width += 2;
304  r2.x -= 1;
305  r2.width += 2;
306  }
307  }
308  if ((x <= a) && (prevy < r2.y))
309  {
310  /* Draw final line */
311  r1.height = r1.y+r1.height-r2.y;
312  r1.y = r2.y;
313 
314  W = w;
315  if (r.x + W != prevx)
316  W = prevx - r.x;
317  if (W < w)
318  W = w;
319 
320  if (W+W >= r.width)
321  {
322  result &= app_fill_rect(g, rect(r.x, r1.y,
323  r.width, r1.height), pbrush, TRUE);
324  return result;
325  }
326 
327  result &= app_fill_rect(g, rect(r.x, r1.y, W, r1.height), pbrush, TRUE);
328  result &= app_fill_rect(g, rect(r.x+r.width-W, r1.y,
329  W, r1.height), pbrush, TRUE);
330  }
331  return result;
332 }
333 
334 /*
335  * Draw an arc of an ellipse from start_angle anti-clockwise to
336  * end_angle. If the angles coincide, draw nothing; if they
337  * differ by 360 degrees or more, draw a full ellipse.
338  * The shape is drawn with the current line thickness,
339  * completely within the bounding rectangle. The shape is also
340  * axis-aligned, so that the ellipse would be horizontally and
341  * vertically symmetric is it was complete.
342  *
343  * The draw_arc algorithm is based on draw_ellipse, but unlike
344  * that algorithm is not symmetric in the general case, since
345  * an angular portion is clipped from the shape.
346  * This clipping is performed by keeping track of two hypothetical
347  * lines joining the centre point to the enclosing rectangle,
348  * at the angles start_angle and end_angle, using a line-intersection
349  * algorithm. Essentially the algorithm just fills the spaces
350  * which are within the arc and also between the angles, going
351  * in an anti-clockwise direction from start_angle to end_angle.
352  * In the top half of the ellipse, this amounts to drawing
353  * to the left of the start_angle line and to the right of
354  * the end_angle line, while in the bottom half of the ellipse,
355  * it involves drawing to the right of the start_angle and to
356  * the left of the end_angle.
357  */
358 
359 /*
360  * Fill a rectangle within an arc, given the centre point p0,
361  * and the two end points of the lines corresponding to the
362  * start_angle and the end_angle. This function takes care of
363  * the logic needed to swap the fill direction below
364  * the central point, and also performs the calculations
365  * needed to intersect the current Y value with each line.
366  */
367 static
368 int
369 FASTCALL
371  Rect r, // top, left, width, height
372  POINT p0, // Center
373  POINT p1, // Start
374  POINT p2, // End
375  int start_angle,
376  int end_angle,
377  PBRUSH pbrush,
378  BOOL Pen)
379 {
380  int x1, x2;
381  int start_above, end_above;
382  long rise1, run1, rise2, run2;
383 
384  rise1 = p1.y - p0.y;
385  run1 = p1.x - p0.x;
386  rise2 = p2.y - p0.y;
387  run2 = p2.x - p0.x;
388 
389  if (r.y <= p0.y) //
390  {
391  /* In top half of arc ellipse */
392 
393  if (p1.y <= r.y)
394  {
395  /* Start_line is in the top half and is */
396  /* intersected by the current Y scan line */
397  if (rise1 == 0)
398  x1 = p1.x;
399  else
400  x1 = p0.x + (r.y-p0.y)*run1/rise1;
401  start_above = 1;
402  }
403  else if ((start_angle >= 0) && (start_angle <= 180))
404  {
405  /* Start_line is above middle */
406  x1 = p1.x;
407  start_above = 1;
408  }
409  else
410  {
411  /* Start_line is below middle */
412  x1 = r.x + r.width;
413  start_above = 0;
414  }
415  if (x1 < r.x)
416  x1 = r.x;
417  if (x1 > r.x+r.width)
418  x1 = r.x+r.width;
419 
420  if (p2.y <= r.y)
421  {
422  /* end_line is in the top half and is */
423  /* intersected by the current Y scan line */
424  if (rise2 == 0)
425  x2 = p2.x;
426  else
427  x2 = p0.x + (r.y-p0.y)*run2/rise2;
428  end_above = 1;
429  }
430  else if ((end_angle >= 0) && (end_angle <= 180))
431  {
432  /* end_line is above middle */
433  x2 = p2.x;
434  end_above = 1;
435  }
436  else
437  {
438  /* end_line is below middle */
439  x2 = r.x;
440  end_above = 0;
441  }
442 
443  if (x2 < r.x) x2 = r.x;
444 
445  if (x2 > r.x+r.width) x2 = r.x+r.width;
446 
447  if (start_above && end_above)
448  {
449  if (start_angle > end_angle)
450  {
451  /* Fill outsides of wedge */
452  if (! app_fill_rect(g, rect(r.x, r.y,
453  x1-r.x, r.height), pbrush, Pen))
454  return 0;
455  return app_fill_rect(g, rect(x2, r.y,
456  r.x+r.width-x2, r.height), pbrush, Pen);
457  }
458  else
459  {
460  /* Fill inside of wedge */
461  r.width = x1-x2;
462  r.x = x2;
463  return app_fill_rect(g, r, pbrush, Pen);
464  }
465  }
466  else if (start_above)
467  {
468  /* Fill to the left of the start_line */
469  r.width = x1-r.x;
470  return app_fill_rect(g, r, pbrush, Pen);
471  }
472  else if (end_above)
473  {
474  /* Fill right of end_line */
475  r.width = r.x+r.width-x2;
476  r.x = x2;
477  return app_fill_rect(g, r, pbrush, Pen);
478  }
479  else
480  {
481  if (start_angle > end_angle)
482  return app_fill_rect(g,r, pbrush, Pen);
483  else
484  return 1;
485  }
486  }
487  else
488  {
489  /* In lower half of arc ellipse */
490 
491  if (p1.y >= r.y)
492  {
493  /* start_line is in the lower half and is */
494  /* intersected by the current Y scan line */
495  if (rise1 == 0)
496  x1 = p1.x;
497  else
498  x1 = p0.x + (r.y-p0.y)*run1/rise1;
499  start_above = 0;
500  }
501  else if ((start_angle >= 180) && (start_angle <= 360))
502  {
503  /* start_line is below middle */
504  x1 = p1.x;
505  start_above = 0;
506  }
507  else
508  {
509  /* start_line is above middle */
510  x1 = r.x;
511  start_above = 1;
512  }
513  if (x1 < r.x)
514  x1 = r.x;
515  if (x1 > r.x+r.width)
516  x1 = r.x+r.width;
517 
518  if (p2.y >= r.y)
519  {
520  /* end_line is in the lower half and is */
521  /* intersected by the current Y scan line */
522  if (rise2 == 0)
523  x2 = p2.x;
524  else
525  x2 = p0.x + (r.y-p0.y)*run2/rise2;
526  end_above = 0;
527  }
528  else if ((end_angle >= 180) && (end_angle <= 360))
529  {
530  /* end_line is below middle */
531  x2 = p2.x;
532  end_above = 0;
533  }
534  else
535  {
536  /* end_line is above middle */
537  x2 = r.x + r.width;
538  end_above = 1;
539  }
540  if (x2 < r.x)
541  x2 = r.x;
542  if (x2 > r.x+r.width)
543  x2 = r.x+r.width;
544 
545  if (start_above && end_above)
546  {
547  if (start_angle > end_angle)
548  return app_fill_rect(g,r, pbrush, Pen);
549  else
550  return 1;
551  }
552  else if (start_above)
553  {
554  /* Fill to the left of end_line */
555  r.width = x2-r.x;
556  return app_fill_rect(g,r, pbrush, Pen);
557  }
558  else if (end_above)
559  {
560  /* Fill right of start_line */
561  r.width = r.x+r.width-x1;
562  r.x = x1;
563  return app_fill_rect(g,r, pbrush, Pen);
564  }
565  else
566  {
567  if (start_angle > end_angle)
568  {
569  /* Fill outsides of wedge */
570  if (! app_fill_rect(g, rect(r.x, r.y,
571  x2-r.x, r.height), pbrush, Pen))
572  return 0;
573  return app_fill_rect(g, rect(x1, r.y,
574  r.x+r.width-x1, r.height), pbrush, Pen);
575  }
576  else
577  {
578  /* Fill inside of wedge */
579  r.width = x2-x1;
580  r.x = x1;
581  return app_fill_rect(g, r, pbrush, Pen);
582  }
583  }
584  }
585 }
586 
587 /*
588  * To fill an axis-aligned ellipse, we use a scan-line algorithm.
589  * We walk downwards from the top Y co-ordinate, calculating
590  * the width of the ellipse using incremental integer arithmetic.
591  * To save calculation, we observe that the top and bottom halves
592  * of the ellipsoid are mirror-images, therefore we can draw the
593  * top and bottom halves by reflection. As a result, this algorithm
594  * draws rectangles inwards from the top and bottom edges of the
595  * bounding rectangle.
596  *
597  * To save rendering time, draw as few rectangles as possible.
598  * Other ellipse-drawing algorithms assume we want to draw each
599  * line, using a draw_pixel operation, or a draw_horizontal_line
600  * operation. This approach is slower than it needs to be in
601  * circumstances where a fill_rect operation is more efficient
602  * (such as in X-Windows, where there is a communication overhead
603  * to the X-Server). For this reason, the algorithm accumulates
604  * rectangles on adjacent lines which have the same width into a
605  * single larger rectangle.
606  *
607  * This algorithm forms the basis of the later, more complex,
608  * draw_ellipse algorithm, which renders the rectangular spaces
609  * between an outer and inner ellipse, and also the draw_arc and
610  * fill_arc operations which additionally clip drawing between
611  * a start_angle and an end_angle.
612  *
613  */
614 static
615 int
616 FASTCALL
618 {
619  /* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
620 
621  int a = r.width / 2;
622  int b = r.height / 2;
623  int x = 0;
624  int y = b;
625  long a2 = a*a;
626  long b2 = b*b;
627  long xcrit = (3 * a2 / 4) + 1;
628  long ycrit = (3 * b2 / 4) + 1;
629  long t = b2 + a2 - 2*a2*b; /* t = e(x+1,y-1) */
630  long dxt = b2*(3+x+x);
631  long dyt = a2*(3-y-y);
632  int d2xt = b2+b2;
633  int d2yt = a2+a2;
634  Rect r1, r2;
635  int result = 1;
636 
637  if ((r.width <= 2) || (r.height <= 2))
638  return app_fill_rect(g, r, pbrush, FALSE);
639 
640  r1.x = r.x + a;
641  r1.y = r.y;
642  r1.width = r.width & 1; /* i.e. if width is odd */
643  r1.height = 1;
644 
645  r2 = r1;
646  r2.y = r.y + r.height - 1;
647 
648  while (y > 0)
649  {
650  if (t + a2*y < xcrit) /* e(x+1,y-1/2) <= 0 */
651  {
652  /* Move outwards to encounter edge */
653  x += 1;
654  t += dxt;
655  dxt += d2xt;
656 
657  /* Move outwards */
658  r1.x -= 1;
659  r1.width += 2;
660  r2.x -= 1;
661  r2.width += 2;
662  }
663  else if (t - b2*x >= ycrit) /* e(x+1/2,y-1) > 0 */
664  {
665  /* Drop down one line */
666  y -= 1;
667  t += dyt;
668  dyt += d2yt;
669 
670  /* Enlarge rectangles */
671  r1.height += 1;
672  r2.height += 1;
673  r2.y -= 1;
674  }
675  else
676  {
677  /* Drop diagonally down and out */
678  x += 1;
679  y -= 1;
680  t += dxt + dyt;
681  dxt += d2xt;
682  dyt += d2yt;
683 
684  if ((r1.width > 0) && (r1.height > 0))
685  {
686  /* Draw rectangles first */
687 
688  if (r1.y+r1.height < r2.y)
689  {
690  /* Distinct rectangles */
691  result &= app_fill_rect(g, r1, pbrush, FALSE);
692  result &= app_fill_rect(g, r2, pbrush, FALSE);
693  }
694 
695  /* Move down */
696  r1.y += r1.height;
697  r1.height = 1;
698  r2.y -= 1;
699  r2.height = 1;
700  }
701  else
702  {
703  /* Skipped pixels on initial diagonal */
704 
705  /* Enlarge, rather than moving down */
706  r1.height += 1;
707  r2.height += 1;
708  r2.y -= 1;
709  }
710 
711  /* Move outwards */
712  r1.x -= 1;
713  r1.width += 2;
714  r2.x -= 1;
715  r2.width += 2;
716  }
717  }
718  if (r1.y < r2.y)
719  {
720  /* Overlap */
721  r1.x = r.x;
722  r1.width = r.width;
723  r1.height = r2.y+r2.height-r1.y;
724  result &= app_fill_rect(g, r1, pbrush, FALSE);
725  }
726  else if (x <= a)
727  {
728  /* Crossover, draw final line */
729  r1.x = r.x;
730  r1.width = r.width;
731  r1.height = r1.y+r1.height-r2.y;
732  r1.y = r2.y;
733  result &= app_fill_rect(g, r1, pbrush, FALSE);
734  }
735  return result;
736 }
737 
738 static
739 POINT
740 FASTCALL
742 {
743  int cx, cy;
744  double tangent;
745 
746  cx = r.width;
747  cx /= 2;
748  cx += r.x;
749 
750  cy = r.height;
751  cy /= 2;
752  cy += r.y;
753 
754  if (angle == 0)
755  return pt(r.x+r.width, cy);
756  else if (angle == 45)
757  return pt(r.x+r.width, r.y);
758  else if (angle == 90)
759  return pt(cx, r.y);
760  else if (angle == 135)
761  return pt(r.x, r.y);
762  else if (angle == 180)
763  return pt(r.x, cy);
764  else if (angle == 225)
765  return pt(r.x, r.y+r.height);
766  else if (angle == 270)
767  return pt(cx, r.y+r.height);
768  else if (angle == 315)
769  return pt(r.x+r.width, r.y+r.height);
770 
771  tangent = tan(DEGREES_TO_RADIANS(angle));
772 
773  if ((angle > 45) && (angle < 135))
774  return pt((int)(cx+r.height/tangent/2), r.y);
775  else if ((angle > 225) && (angle < 315))
776  return pt((int)(cx-r.height/tangent/2), r.y+r.height);
777  else if ((angle > 135) && (angle < 225))
778  return pt(r.x, (int)(cy+r.width*tangent/2));
779  else
780  return pt(r.x+r.width, (int)(cy-r.width*tangent/2));
781 }
782 
783 int
784 FASTCALL
785 app_fill_arc(DC *g, Rect r, int start_angle, int end_angle, PBRUSH pbrush, BOOL Chord)
786 {
787  /* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
788 
789  int a = r.width / 2;
790  int b = r.height / 2;
791  int x = 0;
792  int y = b;
793  long a2 = a*a;
794  long b2 = b*b;
795  long xcrit = (3 * a2 / 4) + 1;
796  long ycrit = (3 * b2 / 4) + 1;
797  long t = b2 + a2 - 2*a2*b; /* t = e(x+1,y-1) */
798  long dxt = b2*(3+x+x);
799  long dyt = a2*(3-y-y);
800  int d2xt = b2+b2;
801  int d2yt = a2+a2;
802  Rect r1, r2;
803  int movedown, moveout;
804  int result = 1;
805 
806  /* Line descriptions */
807  POINT p0, p1, p2;
808 
809  /* If angles differ by 360 degrees or more, close the shape */
810  if ((start_angle + 360 <= end_angle) ||
811  (start_angle - 360 >= end_angle))
812  {
813  return app_fill_ellipse(g, r, pbrush);
814  }
815 
816  /* Make start_angle >= 0 and <= 360 */
817  while (start_angle < 0)
818  start_angle += 360;
819  start_angle %= 360;
820 
821  /* Make end_angle >= 0 and <= 360 */
822  while (end_angle < 0)
823  end_angle += 360;
824  end_angle %= 360;
825 
826  /* Draw nothing if the angles are equal */
827  if (start_angle == end_angle)
828  return 1;
829 
830  /* Find arc wedge line end points */
831  p1 = app_boundary_point(r, start_angle);
832  p2 = app_boundary_point(r, end_angle);
833  if (Chord)
834  p0 = pt((p1.x+p2.x)/2,(p1.y+p2.y)/2);
835  else
836  p0 = pt(r.x + r.width/2, r.y + r.height/2);
837 
838  /* Initialise rectangles to be drawn */
839  r1.x = r.x + a;
840  r1.y = r.y;
841  r1.width = r.width & 1; /* i.e. if width is odd */
842  r1.height = 1;
843 
844  r2 = r1;
845  r2.y = r.y + r.height - 1;
846 
847  while (y > 0)
848  {
849  moveout = movedown = 0;
850 
851  if (t + a2*y < xcrit) /* e(x+1,y-1/2) <= 0 */
852  {
853  /* Move outwards to encounter edge */
854  x += 1;
855  t += dxt;
856  dxt += d2xt;
857 
858  moveout = 1;
859  }
860  else if (t - b2*x >= ycrit) /* e(x+1/2,y-1) > 0 */
861  {
862  /* Drop down one line */
863  y -= 1;
864  t += dyt;
865  dyt += d2yt;
866 
867  movedown = 1;
868  }
869  else
870  {
871  /* Drop diagonally down and out */
872  x += 1;
873  y -= 1;
874  t += dxt + dyt;
875  dxt += d2xt;
876  dyt += d2yt;
877 
878  moveout = 1;
879  movedown = 1;
880  }
881 
882  if (movedown)
883  {
884  if (r1.width == 0)
885  {
886  r1.x -= 1;
887  r1.width += 2;
888  r2.x -= 1;
889  r2.width += 2;
890  moveout = 0;
891  }
892 
893  if (r1.x < r.x)
894  r1.x = r2.x = r.x;
895  if (r1.width > r.width)
896  r1.width = r2.width = r.width;
897  if (r1.y == r2.y-1)
898  {
899  r1.x = r2.x = r.x;
900  r1.width = r2.width = r.width;
901  }
902 
903  if ((r1.width > 0) && (r1.y+r1.height < r2.y))
904  {
905  /* Distinct rectangles */
906  result &= app_fill_arc_rect(g, r1,
907  p0, p1, p2,
908  start_angle, end_angle, pbrush, FALSE);
909  result &= app_fill_arc_rect(g, r2,
910  p0, p1, p2,
911  start_angle, end_angle, pbrush, FALSE);
912  }
913 
914  /* Move down */
915  r1.y += 1;
916  r2.y -= 1;
917  }
918 
919  if (moveout)
920  {
921  /* Move outwards */
922  r1.x -= 1;
923  r1.width += 2;
924  r2.x -= 1;
925  r2.width += 2;
926  }
927  }
928  if (r1.y < r2.y)
929  {
930  /* Overlap */
931  r1.x = r.x;
932  r1.width = r.width;
933  r1.height = r2.y+r2.height-r1.y;
934  while (r1.height > 0)
935  {
936  result &= app_fill_arc_rect(g,
937  rect(r1.x, r1.y, r1.width, 1),
938  p0, p1, p2, start_angle, end_angle, pbrush, FALSE);
939  r1.y += 1;
940  r1.height -= 1;
941  }
942  }
943  else if (x <= a)
944  {
945  /* Crossover, draw final line */
946  r1.x = r.x;
947  r1.width = r.width;
948  r1.height = r1.y+r1.height-r2.y;
949  r1.y = r2.y;
950  while (r1.height > 0)
951  {
952  result &= app_fill_arc_rect(g,
953  rect(r1.x, r1.y, r1.width, 1),
954  p0, p1, p2, start_angle, end_angle, pbrush, FALSE);
955  r1.y += 1;
956  r1.height -= 1;
957  }
958  }
959  return result;
960 }
961 
962 int app_draw_arc(DC *g, Rect r, int start_angle, int end_angle, PBRUSH pbrushPen, BOOL Chord)
963 {
964  /* Outer ellipse: e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
965 
966  int a = r.width / 2;
967  int b = r.height / 2;
968  int x = 0;
969  int y = b;
970  long a2 = a*a;
971  long b2 = b*b;
972  long xcrit = (3 * a2 / 4) + 1;
973  long ycrit = (3 * b2 / 4) + 1;
974  long t = b2 + a2 - 2*a2*b; /* t = e(x+1,y-1) */
975  long dxt = b2*(3+x+x);
976  long dyt = a2*(3-y-y);
977  int d2xt = b2+b2;
978  int d2yt = a2+a2;
979 
980  int w = pbrushPen->lWidth;
981 
982  /* Inner ellipse: E(X,Y) = B*B*X*X + A*A*Y*Y - A*A*B*B */
983 
984  int A = a-w > 0 ? a-w : 0;
985  int B = b-w > 0 ? b-w : 0;
986  int X = 0;
987  int Y = B;
988  long A2 = A*A;
989  long B2 = B*B;
990  long XCRIT = (3 * A2 / 4) + 1;
991  long YCRIT = (3 * B2 / 4) + 1;
992  long T = B2 + A2 - 2*A2*B; /* T = E(X+1,Y-1) */
993  long DXT = B2*(3+X+X);
994  long DYT = A2*(3-Y-Y);
995  int D2XT = B2+B2;
996  int D2YT = A2+A2;
997 
998  /* Arc rectangle calculations */
999  int movedown, moveout;
1000  int innerX = 0, prevx, prevy, W;
1001  Rect r1, r2;
1002  int result = 1;
1003 
1004  /* Line descriptions */
1005  POINT p0, p1, p2;
1006 
1007  /* If angles differ by 360 degrees or more, close the shape */
1008  if ((start_angle + 360 <= end_angle) ||
1009  (start_angle - 360 >= end_angle))
1010  {
1011  return app_draw_ellipse(g, r, pbrushPen);
1012  }
1013 
1014  /* Make start_angle >= 0 and <= 360 */
1015  while (start_angle < 0)
1016  start_angle += 360;
1017  start_angle %= 360;
1018 
1019  /* Make end_angle >= 0 and <= 360 */
1020  while (end_angle < 0)
1021  end_angle += 360;
1022  end_angle %= 360;
1023 
1024  /* Draw nothing if the angles are equal */
1025  if (start_angle == end_angle)
1026  return 1;
1027 
1028  /* Find arc wedge line end points */
1029  p1 = app_boundary_point(r, start_angle);
1030  p2 = app_boundary_point(r, end_angle);
1031  if (Chord)
1032  p0 = pt((p1.x+p2.x)/2,(p1.y+p2.y)/2);
1033  else
1034  p0 = pt(r.x + r.width/2, r.y + r.height/2);
1035 
1036  /* Determine ellipse rectangles */
1037  r1.x = r.x + a;
1038  r1.y = r.y;
1039  r1.width = r.width & 1; /* i.e. if width is odd */
1040  r1.height = 1;
1041 
1042  r2 = r1;
1043  r2.y = r.y + r.height - 1;
1044 
1045  prevx = r1.x;
1046  prevy = r1.y;
1047 
1048  while (y > 0)
1049  {
1050  while (Y == y)
1051  {
1052  innerX = X;
1053 
1054  if (T + A2*Y < XCRIT) /* E(X+1,Y-1/2) <= 0 */
1055  {
1056  /* Move outwards to encounter edge */
1057  X += 1;
1058  T += DXT;
1059  DXT += D2XT;
1060  }
1061  else if (T - B2*X >= YCRIT) /* e(x+1/2,y-1) > 0 */
1062  {
1063  /* Drop down one line */
1064  Y -= 1;
1065  T += DYT;
1066  DYT += D2YT;
1067  }
1068  else
1069  {
1070  /* Drop diagonally down and out */
1071  X += 1;
1072  Y -= 1;
1073  T += DXT + DYT;
1074  DXT += D2XT;
1075  DYT += D2YT;
1076  }
1077  }
1078 
1079  movedown = moveout = 0;
1080 
1081  W = x - innerX;
1082  if (r1.x + W < prevx)
1083  W = prevx - r1.x;
1084  if (W < w)
1085  W = w;
1086 
1087  if (t + a2*y < xcrit) /* e(x+1,y-1/2) <= 0 */
1088  {
1089  /* Move outwards to encounter edge */
1090  x += 1;
1091  t += dxt;
1092  dxt += d2xt;
1093 
1094  moveout = 1;
1095  }
1096  else if (t - b2*x >= ycrit) /* e(x+1/2,y-1) > 0 */
1097  {
1098  /* Drop down one line */
1099  y -= 1;
1100  t += dyt;
1101  dyt += d2yt;
1102 
1103  movedown = 1;
1104  }
1105  else
1106  {
1107  /* Drop diagonally down and out */
1108  x += 1;
1109  y -= 1;
1110  t += dxt + dyt;
1111  dxt += d2xt;
1112  dyt += d2yt;
1113 
1114  movedown = 1;
1115  moveout = 1;
1116  }
1117 
1118  if (movedown)
1119  {
1120  if (r1.width == 0)
1121  {
1122  r1.x -= 1;
1123  r1.width += 2;
1124  r2.x -= 1;
1125  r2.width += 2;
1126  moveout = 0;
1127  }
1128 
1129  if (r1.x < r.x)
1130  r1.x = r2.x = r.x;
1131  if (r1.width > r.width)
1132  r1.width = r2.width = r.width;
1133  if (r1.y == r2.y-1)
1134  {
1135  r1.x = r2.x = r.x;
1136  r1.width = r2.width = r.width;
1137  }
1138 
1139  if ((r1.y < r.y+w) || (r1.x+W >= r1.x+r1.width-W))
1140  {
1141  result &= app_fill_arc_rect(g, r1,
1142  p0, p1, p2,
1143  start_angle, end_angle, pbrushPen, TRUE);
1144  result &= app_fill_arc_rect(g, r2,
1145  p0, p1, p2,
1146  start_angle, end_angle, pbrushPen, TRUE);
1147 
1148  prevx = r1.x;
1149  prevy = r1.y;
1150  }
1151  else if (r1.y+r1.height < r2.y)
1152  {
1153  /* Draw distinct rectangles */
1154  result &= app_fill_arc_rect(g, rect(
1155  r1.x,r1.y,W,1),
1156  p0, p1, p2,
1157  start_angle, end_angle, pbrushPen, TRUE);
1158  result &= app_fill_arc_rect(g, rect(
1159  r1.x+r1.width-W,r1.y,W,1),
1160  p0, p1, p2,
1161  start_angle, end_angle, pbrushPen, TRUE);
1162  result &= app_fill_arc_rect(g, rect(
1163  r2.x,r2.y,W,1),
1164  p0, p1, p2,
1165  start_angle, end_angle, pbrushPen, TRUE);
1166  result &= app_fill_arc_rect(g, rect(
1167  r2.x+r2.width-W,r2.y,W,1),
1168  p0, p1, p2,
1169  start_angle, end_angle, pbrushPen, TRUE);
1170 
1171  prevx = r1.x;
1172  prevy = r1.y;
1173  }
1174 
1175  /* Move down */
1176  r1.y += 1;
1177  r2.y -= 1;
1178  }
1179 
1180  if (moveout)
1181  {
1182  /* Move outwards */
1183  r1.x -= 1;
1184  r1.width += 2;
1185  r2.x -= 1;
1186  r2.width += 2;
1187  }
1188  }
1189  if ((x <= a) && (prevy < r2.y))
1190  {
1191  /* Draw final lines */
1192  r1.height = r1.y+r1.height-r2.y;
1193  r1.y = r2.y;
1194 
1195  W = w;
1196  if (r.x + W != prevx)
1197  W = prevx - r.x;
1198  if (W < w)
1199  W = w;
1200 
1201  if (W+W >= r.width)
1202  {
1203  while (r1.height > 0)
1204  {
1205  result &= app_fill_arc_rect(g, rect(r.x,
1206  r1.y, r.width, 1), p0, p1, p2,
1207  start_angle, end_angle, pbrushPen, TRUE);
1208  r1.y += 1;
1209  r1.height -= 1;
1210  }
1211  return result;
1212  }
1213 
1214  while (r1.height > 0)
1215  {
1216  result &= app_fill_arc_rect(g, rect(r.x, r1.y,
1217  W, 1), p0, p1, p2,
1218  start_angle, end_angle, pbrushPen, TRUE);
1219  result &= app_fill_arc_rect(g, rect(r.x+r.width-W,
1220  r1.y, W, 1), p0, p1, p2,
1221  start_angle, end_angle, pbrushPen, TRUE);
1222  r1.y += 1;
1223  r1.height -= 1;
1224  }
1225  }
1226 
1227  return result;
1228 }
1229 
1230 /* ReactOS Interface *********************************************************/
1231 
1232 int
1233 FASTCALL
1235  INT XLeft,
1236  INT YLeft,
1237  INT Width,
1238  INT Height,
1239  PBRUSH pbrush,
1240  BOOL Pen)
1241 {
1243  RECTL DestRect;
1244  SURFACE *psurf;
1245  POINTL BrushOrigin;
1246  BOOL Ret = TRUE;
1247  PDC_ATTR pdcattr;
1248 
1249  ASSERT(pbrush);
1250  ASSERT_DC_PREPARED(dc);
1251 
1252  psurf = dc->dclevel.pSurface;
1253  if (psurf == NULL)
1254  {
1256  return 0;
1257  }
1258 
1259  if (!(pbrush->flAttrs & BR_IS_NULL))
1260  {
1261  pdcattr = dc->pdcattr;
1262 
1263  /* Fix negative spaces */
1264  if (Width < 0)
1265  {
1266  XLeft += Width;
1267  Width = 0 - Width;
1268  }
1269  if (Height < 0)
1270  {
1271  YLeft += Height;
1272  Height = 0 - Height;
1273  }
1274 
1275  DestRect.left = XLeft;
1276  DestRect.right = XLeft + Width;
1277 
1278  DestRect.top = YLeft;
1279  DestRect.bottom = YLeft + Height;
1280 
1281  BrushOrigin.x = pbrush->ptOrigin.x;
1282  BrushOrigin.y = pbrush->ptOrigin.y;
1283 
1284  if (pdcattr->jROP2 == R2_XORPEN)
1286 
1287  Ret = IntEngBitBlt(
1288  &psurf->SurfObj,
1289  NULL,
1290  NULL,
1291  (CLIPOBJ *)&dc->co,
1292  NULL,
1293  &DestRect,
1294  NULL,
1295  NULL,
1296  Pen ? &dc->eboLine.BrushObject : &dc->eboFill.BrushObject,
1297  &BrushOrigin,
1298  ROP);
1299  }
1300 
1301  return (int)Ret;
1302 }
1303 
1304 BOOL
1305 FASTCALL
1307  INT XLeft,
1308  INT YLeft,
1309  INT Width,
1310  INT Height,
1311  double StartArc, // FIXME: don't use floating point!
1312  double EndArc,
1313  ARCTYPE arctype)
1314 {
1315  PDC_ATTR pdcattr;
1316  PBRUSH pbrush;
1317  int Start = (int)ceil(StartArc);
1318  int End = (int)ceil(EndArc);
1319  BOOL Chord = (arctype == GdiTypeChord), ret;
1320 
1321  pdcattr = dc->pdcattr;
1322 
1323  pbrush = BRUSH_ShareLockBrush(pdcattr->hbrush);
1324  if (!pbrush)
1325  {
1326  DPRINT1("FillArc Fail\n");
1328  return FALSE;
1329  }
1330  // Sort out alignment here.
1331  ret = app_fill_arc(dc, rect( XLeft, YLeft, Width, Height),
1332  (dc->dclevel.flPath & DCPATH_CLOCKWISE) ? -End : -Start,
1333  (dc->dclevel.flPath & DCPATH_CLOCKWISE) ? -Start : -End,
1334  pbrush, Chord);
1335 
1336  BRUSH_ShareUnlockBrush(pbrush);
1337  return ret;
1338 }
1339 
1340 BOOL
1341 FASTCALL
1343  INT XLeft,
1344  INT YLeft,
1345  INT Width,
1346  INT Height,
1347  double StartArc, // FIXME: don't use floating point!
1348  double EndArc,
1349  ARCTYPE arctype,
1350  PBRUSH pbrush)
1351 {
1352  int Start = (int)ceil(StartArc);
1353  int End = (int)ceil(EndArc);
1354  BOOL Chord = (arctype == GdiTypeChord);
1355  // Sort out alignment here.
1356  return app_draw_arc(dc, rect( XLeft, YLeft, Width, Height),
1357  (dc->dclevel.flPath & DCPATH_CLOCKWISE) ? -End : -Start,
1358  (dc->dclevel.flPath & DCPATH_CLOCKWISE) ? -Start : -End,
1359  pbrush, Chord);
1360 }
1361 
1362 BOOL
1363 FASTCALL
1365  INT XLeft,
1366  INT YLeft,
1367  INT Width,
1368  INT Height,
1369  PBRUSH pbrush)
1370 {
1371  return (BOOL)app_draw_ellipse(dc, rect( XLeft, YLeft, Width, Height), pbrush);
1372 }
1373 
1374 BOOL
1375 FASTCALL
1377  INT XLeft,
1378  INT YLeft,
1379  INT Width,
1380  INT Height,
1381  PBRUSH pbrush)
1382 {
1383  return (BOOL)app_fill_ellipse(dc, rect( XLeft, YLeft, Width, Height), pbrush);
1384 }
1385 
1386 BOOL
1387 FASTCALL
1389  INT Left,
1390  INT Top,
1391  INT Right,
1392  INT Bottom,
1393  INT Wellipse,
1394  INT Hellipse,
1395  PBRUSH pbrush)
1396 {
1397  Rect r;
1398  int rx, ry; /* Radius in x and y directions */
1399 
1400  // x y Width Height
1401  r = rect( Left, Top, abs(Right-Left), abs(Bottom-Top));
1402  rx = Wellipse/2;
1403  ry = Hellipse/2;
1404 
1405  if (Wellipse > r.width)
1406  {
1407  if (Hellipse > r.height) // > W > H
1408  app_fill_ellipse(dc, r, pbrush);
1409  else // > W < H
1410  {
1411  app_fill_arc(dc, rect( r.x, r.y, r.width - 1, Hellipse),
1412  0, 180, pbrush,FALSE);
1413  app_fill_arc(dc, rect(r.x, Bottom - Hellipse - 1, r.width - 1, Hellipse),
1414  180, 360, pbrush, FALSE);
1415  }
1416  }
1417  else if(Hellipse > r.height) // < W > H
1418  {
1419  app_fill_arc(dc, rect(r.x, r.y, Wellipse, r.height - 1),
1420  90, 270, pbrush, FALSE);
1421  app_fill_arc(dc, rect(Right - Wellipse - 1, r.y, Wellipse, r.height - 1),
1422  270, 90, pbrush,FALSE);
1423  }
1424  else // < W < H
1425  {
1426  app_fill_arc(dc, rect(r.x, r.y, rx+rx, ry+ry),
1427  90, 180, pbrush, FALSE);
1428 
1429  app_fill_arc(dc, rect(r.x, r.y+r.height-ry-ry, rx+rx, ry+ry),
1430  180, 270, pbrush, FALSE);
1431 
1432  app_fill_arc(dc, rect(r.x+r.width-rx-rx, r.y+r.height-ry-ry, rx+rx, ry+ry),
1433  270, 360, pbrush,FALSE);
1434 
1435  app_fill_arc(dc, rect(r.x+r.width-rx-rx, r.y, rx+rx, ry+ry),
1436  0, 90, pbrush,FALSE);
1437  }
1438  if (Wellipse < r.width)
1439  {
1440  app_fill_rect(dc, rect(r.x+rx, r.y, r.width-rx-rx, ry+1), pbrush, FALSE);
1441  app_fill_rect(dc, rect(r.x+rx, r.y+r.height-ry+1, r.width-rx-rx, ry-1), pbrush, FALSE);
1442  }
1443  if (Hellipse < r.height)
1444  {
1445  app_fill_rect(dc, rect(r.x, r.y+ry+1, r.width, r.height-ry-ry), pbrush, FALSE);
1446  }
1447 
1448  return TRUE;
1449 }
1450 
1451 
1452 BOOL
1453 FASTCALL
1455  INT Left,
1456  INT Top,
1457  INT Right,
1458  INT Bottom,
1459  INT Wellipse,
1460  INT Hellipse,
1461  PBRUSH pbrushPen)
1462 {
1463  Rect r;
1464  int rx, ry; /* Radius in x and y directions */
1465  int w = pbrushPen->lWidth;
1466 
1467  r = rect( Left, Top, abs(Right-Left), abs(Bottom-Top));
1468  rx = Wellipse/2;
1469  ry = Hellipse/2;
1470 
1471  if (Wellipse > r.width)
1472  {
1473  if (Hellipse > r.height) // > W > H
1474  app_draw_ellipse(dc, r, pbrushPen);
1475  else // > W < H
1476  {
1477  app_draw_arc(dc, rect( r.x, r.y, r.width - 1, Hellipse - 1),
1478  0, 180, pbrushPen, FALSE);
1479  app_draw_arc(dc, rect(r.x, Bottom - Hellipse, r.width - 1, Hellipse - 1),
1480  180, 360, pbrushPen, FALSE);
1481  }
1482  }
1483  else if(Hellipse > r.height) // < W > H
1484  {
1485  app_draw_arc(dc, rect(r.x, r.y, Wellipse - 1, r.height - 1),
1486  90, 270, pbrushPen, FALSE);
1487  app_draw_arc(dc, rect(Right - Wellipse, r.y, Wellipse - 1, r.height - 1),
1488  270, 90, pbrushPen, FALSE);
1489  }
1490  else // < W < H
1491  {
1492  app_draw_arc(dc, rect(r.x, r.y, rx+rx, ry+ry),
1493  90, 180, pbrushPen, FALSE);
1494 
1495  app_draw_arc(dc, rect(r.x,r.y+r.height-ry-ry,rx+rx,ry+ry),
1496  180, 270, pbrushPen, FALSE);
1497 
1498  app_draw_arc(dc, rect(r.x+r.width-rx-rx, r.y+r.height-ry-ry, rx+rx, ry+ry),
1499  270, 360, pbrushPen, FALSE);
1500 
1501  app_draw_arc(dc, rect(r.x+r.width-rx-rx,r.y,rx+rx,ry+ry),
1502  0, 90, pbrushPen, FALSE);
1503  }
1504  if ( Hellipse < r.height)
1505  {
1506  app_fill_rect(dc, rect(r.x, r.y+ry+1, w, r.height-ry-ry), pbrushPen, TRUE);
1507 
1508 
1509  app_fill_rect(dc, rect(r.x+r.width-w, r.y+ry+1, w, r.height-ry-ry),
1510  pbrushPen, TRUE);
1511  }
1512  if ( Wellipse < r.width)
1513  {
1514  app_fill_rect(dc, rect(r.x+rx, r.y+r.height-w, r.width-rx-rx, w),
1515  pbrushPen, TRUE);
1516 
1517  app_fill_rect(dc, rect(r.x+rx, r.y, r.width-rx-rx, w), pbrushPen, TRUE);
1518  }
1519  return TRUE;
1520 }
1521 
#define BRUSH_ShareUnlockBrush(pBrush)
Definition: brush.h:114
_Check_return_ _CRTIMP double __cdecl ceil(_In_ double x)
#define abs(i)
Definition: fconv.c:206
int x
Definition: drawing.c:62
#define TRUE
Definition: types.h:120
int FASTCALL IntFillRect(DC *dc, INT XLeft, INT YLeft, INT Width, INT Height, PBRUSH pbrush, BOOL Pen)
Definition: drawing.c:1234
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
long y
Definition: polytest.cpp:48
#define app_fill_rect(dc, r, BrushObj, Pen)
Definition: drawing.c:107
#define ERROR_INTERNAL_ERROR
Definition: winerror.h:840
int width
Definition: drawing.c:63
struct _Rect * PRect
long x
Definition: polytest.cpp:48
BOOL FASTCALL IntDrawArc(PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype, PBRUSH pbrush)
Definition: drawing.c:1342
HANDLE hbrush
Definition: ntgdihdl.h:292
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define BRUSH_ShareLockBrush(hBrush)
Definition: brush.h:113
#define pt(x, y)
Definition: drawing.c:79
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
static DNS_RECORDW r1
Definition: record.c:36
BOOL FASTCALL IntDrawRoundRect(PDC dc, INT Left, INT Top, INT Right, INT Bottom, INT Wellipse, INT Hellipse, PBRUSH pbrushPen)
Definition: drawing.c:1454
long bottom
Definition: polytest.cpp:53
GLdouble GLdouble t
Definition: gl.h:2047
BOOL FASTCALL IntDrawEllipse(PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, PBRUSH pbrush)
Definition: drawing.c:1364
BOOL WINAPI Chord(_In_ HDC hdc, _In_ INT xLeft, _In_ INT yTop, _In_ INT xRight, _In_ INT yBottom, _In_ INT xRadial1, _In_ INT yRadial1, _In_ INT xRadial2, _In_ INT yRadial2)
Definition: arc.c:113
#define Y(i)
Definition: t_vb_render.c:49
HDC dc
Definition: cylfrac.c:34
GLfloat angle
Definition: glext.h:10853
struct _Rect Rect
#define FASTCALL
Definition: nt_native.h:50
int32_t INT
Definition: typedefs.h:56
#define T
Definition: mbstring.h:31
DWORD DWORD
Definition: winlogon.h:75
LONG y
Definition: windef.h:343
Definition: drawing.c:60
BOOL FASTCALL IntFillArc(PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype)
Definition: drawing.c:1306
const GLfloat * p2
Definition: s_aatritemp.h:44
#define DEGREES_TO_RADIANS(deg)
Definition: drawing.c:58
long right
Definition: polytest.cpp:53
static Rect NTAPI rect(int x, int y, int width, int height)
Definition: drawing.c:84
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
#define a
Definition: ke_i.h:78
long top
Definition: polytest.cpp:53
int y
Definition: drawing.c:62
SURFOBJ SurfObj
Definition: surface.h:8
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:570
smooth NULL
Definition: ftsmooth.c:557
const GLfloat * p0
Definition: s_aatritemp.h:42
int app_draw_arc(DC *g, Rect r, int start_angle, int end_angle, PBRUSH pbrushPen, BOOL Chord)
Definition: drawing.c:962
#define R2_XORPEN
Definition: wingdi.h:351
long left
Definition: polytest.cpp:53
#define b
Definition: ke_i.h:79
Definition: types.h:100
int FASTCALL app_fill_arc(DC *g, Rect r, int start_angle, int end_angle, PBRUSH pbrush, BOOL Chord)
Definition: drawing.c:785
GLboolean GLboolean g
Definition: glext.h:6204
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
Definition: polytest.cpp:40
unsigned int BOOL
Definition: ntddk_ex.h:94
GLint GLint GLsizei width
Definition: gl.h:1546
static const struct update_accum a2
Definition: msg.c:586
BYTE jROP2
Definition: ntgdihdl.h:304
static DNS_RECORDW r2
Definition: record.c:37
#define BR_IS_NULL
Definition: brush.h:101
LONG x
Definition: windef.h:342
#define A(row, col)
Definition: m_matrix.c:145
struct W W
int height
Definition: drawing.c:63
int ret
Definition: ttei1.cpp:12
#define ASSERT_DC_PREPARED(pdc)
Definition: dc.h:299
static POINT FASTCALL app_boundary_point(Rect r, int angle)
Definition: drawing.c:741
static int FASTCALL app_fill_ellipse(DC *g, Rect r, PBRUSH pbrush)
Definition: drawing.c:617
Definition: bidi.c:91
BOOL FASTCALL IntFillEllipse(PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, PBRUSH pbrush)
Definition: drawing.c:1376
static LPHIST_ENTRY Bottom
Definition: history.c:54
enum _ARCTYPE ARCTYPE
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
static int NTAPI app_draw_ellipse(DC *g, Rect r, PBRUSH pbrush)
Definition: drawing.c:124
static POINT NTAPI app_new_point(int x, int y)
Definition: drawing.c:72
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3706
#define DPRINT1
Definition: precomp.h:8
BOOL FASTCALL IntFillRoundRect(PDC dc, INT Left, INT Top, INT Right, INT Bottom, INT Wellipse, INT Hellipse, PBRUSH pbrush)
Definition: drawing.c:1388
_Out_opt_ int * cx
Definition: commctrl.h:570
static CRYPT_DATA_BLOB b2[]
Definition: msg.c:582
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLfloat GLfloat p
Definition: glext.h:8902
const GLfloat * p1
Definition: s_aatritemp.h:43
_STLP_DECLSPEC complex< float > _STLP_CALL tan(const complex< float > &)
INT INT y
Definition: msvc.h:62
Definition: gdipluspen.h:24
GLuint64EXT * result
Definition: glext.h:11304
static int FASTCALL app_fill_arc_rect(DC *g, Rect r, POINT p0, POINT p1, POINT p2, int start_angle, int end_angle, PBRUSH pbrush, BOOL Pen)
Definition: drawing.c:370
static LPHIST_ENTRY Top
Definition: history.c:53
#define ROP4_FROM_INDEX(index)
Definition: inteng.h:42
Definition: partlist.h:39
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
#define X(b, s)
BOOL APIENTRY IntEngBitBlt(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo, RECTL *prclTrg, POINTL *pptlSrc, POINTL *pptlMask, BRUSHOBJ *pbo, POINTL *pptlBrush, ROP4 Rop4)
Definition: bitblt.c:604
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:29
INT x
Definition: msvc.h:62