arc.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <draw.h>
  12. #include <memdraw.h>
  13. #include <memlayer.h>
  14. /*
  15. * elarc(dst,c,a,b,t,src,sp,alpha,phi)
  16. * draws the part of an ellipse between rays at angles alpha and alpha+phi
  17. * measured counterclockwise from the positive x axis. other
  18. * arguments are as for ellipse(dst,c,a,b,t,src,sp)
  19. */
  20. enum
  21. {
  22. R, T, L, B /* right, top, left, bottom */
  23. };
  24. static
  25. Point corners[] = {
  26. {1,1},
  27. {-1,1},
  28. {-1,-1},
  29. {1,-1}
  30. };
  31. static
  32. Point p00;
  33. /*
  34. * make a "wedge" mask covering the desired angle and contained in
  35. * a surrounding square; draw a full ellipse; intersect that with the
  36. * wedge to make a mask through which to copy src to dst.
  37. */
  38. void
  39. memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi, int op)
  40. {
  41. int i, w, beta, tmp, c1, c2, m, m1;
  42. Rectangle rect;
  43. Point p, bnd[8];
  44. Memimage *wedge, *figure, *mask;
  45. if(a < 0)
  46. a = -a;
  47. if(b < 0)
  48. b = -b;
  49. w = t;
  50. if(w < 0)
  51. w = 0;
  52. alpha = -alpha; /* compensate for upside-down coords */
  53. phi = -phi;
  54. beta = alpha + phi;
  55. if(phi < 0){
  56. tmp = alpha;
  57. alpha = beta;
  58. beta = tmp;
  59. phi = -phi;
  60. }
  61. if(phi >= 360){
  62. memellipse(dst, c, a, b, t, src, sp, op);
  63. return;
  64. }
  65. while(alpha < 0)
  66. alpha += 360;
  67. while(beta < 0)
  68. beta += 360;
  69. c1 = alpha/90 & 3; /* number of nearest corner */
  70. c2 = beta/90 & 3;
  71. /*
  72. * icossin returns point at radius ICOSSCALE.
  73. * multiplying by m1 moves it outside the ellipse
  74. */
  75. rect = Rect(-a-w, -b-w, a+w+1, b+w+1);
  76. m = rect.max.x; /* inradius of bounding square */
  77. if(m < rect.max.y)
  78. m = rect.max.y;
  79. m1 = (m+ICOSSCALE-1) >> 10;
  80. m = m1 << 10; /* assure m1*cossin is inside */
  81. i = 0;
  82. bnd[i++] = Pt(0,0);
  83. icossin(alpha, &p.x, &p.y);
  84. bnd[i++] = mulpt(p, m1);
  85. for(;;) {
  86. bnd[i++] = mulpt(corners[c1], m);
  87. if(c1==c2 && phi<180)
  88. break;
  89. c1 = (c1+1) & 3;
  90. phi -= 90;
  91. }
  92. icossin(beta, &p.x, &p.y);
  93. bnd[i++] = mulpt(p, m1);
  94. figure = nil;
  95. mask = nil;
  96. wedge = allocmemimage(rect, GREY1);
  97. if(wedge == nil)
  98. goto Return;
  99. memfillcolor(wedge, DTransparent);
  100. memfillpoly(wedge, bnd, i, ~0, memopaque, p00, S);
  101. figure = allocmemimage(rect, GREY1);
  102. if(figure == nil)
  103. goto Return;
  104. memfillcolor(figure, DTransparent);
  105. memellipse(figure, p00, a, b, t, memopaque, p00, S);
  106. mask = allocmemimage(rect, GREY1);
  107. if(mask == nil)
  108. goto Return;
  109. memfillcolor(mask, DTransparent);
  110. memimagedraw(mask, rect, figure, rect.min, wedge, rect.min, S);
  111. c = subpt(c, dst->r.min);
  112. memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(p00, c), op);
  113. Return:
  114. freememimage(wedge);
  115. freememimage(figure);
  116. freememimage(mask);
  117. }