a
This commit is contained in:
117
libmemdraw/arc.c
Normal file
117
libmemdraw/arc.c
Normal file
@ -0,0 +1,117 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
#include <memlayer.h>
|
||||
|
||||
/*
|
||||
* elarc(dst,c,a,b,t,src,sp,alpha,phi)
|
||||
* draws the part of an ellipse between rays at angles alpha and alpha+phi
|
||||
* measured counterclockwise from the positive x axis. other
|
||||
* arguments are as for ellipse(dst,c,a,b,t,src,sp)
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
R, T, L, B /* right, top, left, bottom */
|
||||
};
|
||||
|
||||
static
|
||||
Point corners[] = {
|
||||
{1,1},
|
||||
{-1,1},
|
||||
{-1,-1},
|
||||
{1,-1}
|
||||
};
|
||||
|
||||
static
|
||||
Point p00;
|
||||
|
||||
/*
|
||||
* make a "wedge" mask covering the desired angle and contained in
|
||||
* a surrounding square; draw a full ellipse; intersect that with the
|
||||
* wedge to make a mask through which to copy src to dst.
|
||||
*/
|
||||
void
|
||||
memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi, int op)
|
||||
{
|
||||
int i, w, beta, tmp, c1, c2, m, m1;
|
||||
Rectangle rect;
|
||||
Point p, bnd[8];
|
||||
Memimage *wedge, *figure, *mask;
|
||||
|
||||
if(a < 0)
|
||||
a = -a;
|
||||
if(b < 0)
|
||||
b = -b;
|
||||
w = t;
|
||||
if(w < 0)
|
||||
w = 0;
|
||||
alpha = -alpha; /* compensate for upside-down coords */
|
||||
phi = -phi;
|
||||
beta = alpha + phi;
|
||||
if(phi < 0){
|
||||
tmp = alpha;
|
||||
alpha = beta;
|
||||
beta = tmp;
|
||||
phi = -phi;
|
||||
}
|
||||
if(phi >= 360){
|
||||
memellipse(dst, c, a, b, t, src, sp, op);
|
||||
return;
|
||||
}
|
||||
while(alpha < 0)
|
||||
alpha += 360;
|
||||
while(beta < 0)
|
||||
beta += 360;
|
||||
c1 = alpha/90 & 3; /* number of nearest corner */
|
||||
c2 = beta/90 & 3;
|
||||
/*
|
||||
* icossin returns point at radius ICOSSCALE.
|
||||
* multiplying by m1 moves it outside the ellipse
|
||||
*/
|
||||
rect = Rect(-a-w, -b-w, a+w+1, b+w+1);
|
||||
m = rect.max.x; /* inradius of bounding square */
|
||||
if(m < rect.max.y)
|
||||
m = rect.max.y;
|
||||
m1 = (m+ICOSSCALE-1) >> 10;
|
||||
m = m1 << 10; /* assure m1*cossin is inside */
|
||||
i = 0;
|
||||
bnd[i++] = Pt(0,0);
|
||||
icossin(alpha, &p.x, &p.y);
|
||||
bnd[i++] = mulpt(p, m1);
|
||||
for(;;) {
|
||||
bnd[i++] = mulpt(corners[c1], m);
|
||||
if(c1==c2 && phi<180)
|
||||
break;
|
||||
c1 = (c1+1) & 3;
|
||||
phi -= 90;
|
||||
}
|
||||
icossin(beta, &p.x, &p.y);
|
||||
bnd[i++] = mulpt(p, m1);
|
||||
|
||||
figure = nil;
|
||||
mask = nil;
|
||||
wedge = allocmemimage(rect, GREY1);
|
||||
if(wedge == nil)
|
||||
goto Return;
|
||||
memfillcolor(wedge, DTransparent);
|
||||
memfillpoly(wedge, bnd, i, ~0, memopaque, p00, S);
|
||||
figure = allocmemimage(rect, GREY1);
|
||||
if(figure == nil)
|
||||
goto Return;
|
||||
memfillcolor(figure, DTransparent);
|
||||
memellipse(figure, p00, a, b, t, memopaque, p00, S);
|
||||
mask = allocmemimage(rect, GREY1);
|
||||
if(mask == nil)
|
||||
goto Return;
|
||||
memfillcolor(mask, DTransparent);
|
||||
memimagedraw(mask, rect, figure, rect.min, wedge, rect.min, S);
|
||||
c = subpt(c, dst->r.min);
|
||||
memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(p00, c), op);
|
||||
|
||||
Return:
|
||||
freememimage(wedge);
|
||||
freememimage(figure);
|
||||
freememimage(mask);
|
||||
}
|
Reference in New Issue
Block a user